home *** CD-ROM | disk | FTP | other *** search
/ Racing Games (Spidla) / zavodni.iso / Fun Racing / src / FRApp.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2003-06-19  |  62.7 KB  |  2,177 lines

  1.  
  2. #include "FRApp.h"
  3. /*
  4. FROpponent FRApp::ms_aOpponents[25] = { FROpponent("staddl", PICKUP, 1.8f, true), FROpponent("mp5", GOLF, 1.7f, true),
  5. FROpponent("Red Menace", GOLF, 1.7f, true), FROpponent("Linus T", ACLASS, 1.7f, true), FROpponent("John C", MONSTERHUMMER, 1.7f, true), 
  6. FROpponent("RoadPsycho", HUMMER, 1.6f, true), FROpponent("PsychoDad", HUMMER, 1.6f, true), FROpponent("Al Bundy", DODGE, 1.6f, true), 
  7. FROpponent("Tux", ACLASS, 1.6f, false), FROpponent("Homer Jay", DODGE, 1.5f, true), FROpponent("Doomer", FUNERALCAR, 1.5f, true), 
  8. FROpponent("The Duke", HUMMER, 1.5f, true), FROpponent("Stoned Zivi", AMBULANCE, 1.5f, false), FROpponent("EvilMan", GOLF, 1.4f, true), 
  9. FROpponent("The Devil Himself", MONSTERHUMMER, 1.4f, true), FROpponent("Eat My Shorts", AMBULANCE, 1.4f, true),
  10. FROpponent("Undertaker", FUNERALCAR, 1.4f, true), FROpponent("Pot Express", PICKUP, 1.3f, false), FROpponent("EvilWoman", ACLASS, 1.3f, false),
  11. FROpponent("Mr. Jack", COP, 1.3f, true), FROpponent("Mr. Nice Guy", PICKUP, 1.3f, false), FROpponent("William G", DODGE, 0.8f, false), 
  12. FROpponent("Mary Jane", PICKUP, 1.0f, false), FROpponent("Headshot", COP, 1.1f, true), FROpponent("Brainless", COP, 1.0f, true)};
  13. */
  14. FROpponent FRApp::ms_aOpponents[25] = { FROpponent("staddl", PICKUP, 2.0f, true), FROpponent("mp5", GOLF, 1.9f, true),
  15. FROpponent("Red Menace", GOLF, 1.9f, true), FROpponent("El Barto", DODGE, 1.8f, true), FROpponent("Wide Load", MONSTERHUMMER, 1.8f, true), 
  16. FROpponent("Pot Express", PICKUP, 1.8f, false), FROpponent("Mr. Nice Guy", PICKUP, 1.8f, false), FROpponent("Mr. Shoe", DODGE, 1.8f, true), 
  17. FROpponent("Der Blubb", ACLASS, 1.7f, false), FROpponent("Homer Jay", DODGE, 1.7f, true), FROpponent("Mr. Jack", COP, 1.7f, true), 
  18. FROpponent("The Duke", HUMMER, 1.7f, true), FROpponent("Brainless", COP, 1.65f, true), FROpponent("Evil Man", GOLF, 1.6f, true), 
  19. FROpponent("The Devil Himself", MONSTERHUMMER, 1.6f, true), FROpponent("Eat My Shorts", AMBULANCE, 1.5f, true),
  20. FROpponent("Evil Woman", ACLASS, 1.5f, false), FROpponent("Undertaker", FUNERALCAR, 1.5f, true), FROpponent("Road Psycho", HUMMER, 1.4f, true),
  21. FROpponent("Doomer", FUNERALCAR, 1.4f, true), FROpponent("Psycho Dad", HUMMER, 1.4f, true), FROpponent("Student Driver", ACLASS, 1.0f, false), 
  22. FROpponent("Mary Jane", PICKUP, 1.3f, false), FROpponent("Headshot", COP, 1.2f, true), FROpponent("Stoned Medic", AMBULANCE, 1.0f, false)};
  23.  
  24.  
  25. FRCareerRace FRApp::ms_aRaces[10] = {
  26.     FRCareerRace("Ambulance Trophy", "Ambulance cars are VERY slow.", "But with your siren on, everybody", "has to let you through!", NORMALRACE, true, AMBULANCE), 
  27.     FRCareerRace("Dope Trophy", "The drug business is very hard.", "Because of that, the cars that transport", "the dope are not only fast, but also armed!", POWERUPKO, true, PICKUP), 
  28.     FRCareerRace("Funeral Cup", "Digging graves is a hard job.", "But some undertakers have a hobby, that", "creates distraction and new CUSTOMERS!", RACETODEATH, true, FUNERALCAR), 
  29.     FRCareerRace("Police Chase", "Cops don't only beat innocent people with their", "truncheons, they also do high speed chases.", "Show that you can do it better!", KNOCKOUT, true, COP), 
  30.     FRCareerRace("Army Training", "The army has the best toys available.", "They are bigger, better and a lot of fun.", "Let's test them!", POWERUPRACE, true, HUMMER), 
  31.     FRCareerRace("Fun Skeet Trophy", "You don't know Fun Skeet 2?", "Then go get it under www.funskeet.de.vu!", "{Sorry for the shameless advertising ;)}", RACETODEATH, false, ACLASS), 
  32.     FRCareerRace("Roach Cup", "Cockroaches could survive a nuclear", "armageddon. But do they also survive a car", "running over them with 250 km/h?", POWERUPKO, false, ACLASS), 
  33.     FRCareerRace("Caffeine Race", "Caffeine is GOOD!", "Everybody who says something", "else is a bitch.", KNOCKOUT, false, ACLASS), 
  34.     FRCareerRace("2Fast4U Challenge", "Who's the fastest?", "Like in many other games,", "this is the question here, too.", NORMALRACE, false, ACLASS), 
  35.     FRCareerRace("Illegal Weapon Race", "Just tuning your car is boring!", "Arming your car with any weapon", "you can get is much more interesting!", POWERUPRACE, false, ACLASS)};
  36.  
  37. Char FRApp::ms_aacTrackNames[NUM_TRACKS][12] = {"airfield", "church", "hillhole", "railroad", "windydesert"};
  38.  
  39. TERTTIImplementation(FRAClass, FRCar);
  40. TERTTIImplementation(FRAmbulance, FRCar);
  41. TERTTIImplementation(FRCop, FRCar);
  42. TERTTIImplementation(FRDodge, FRCar);
  43. TERTTIImplementation(FRFuneralCar, FRCar);
  44. TERTTIImplementation(FRGolf, FRCar);
  45. TERTTIImplementation(FRHummer, FRCar);
  46. TERTTIImplementation(FRMonsterHummer, FRCar);
  47. TERTTIImplementation(FRPickup, FRCar);
  48.  
  49. FRApp FunRacing;
  50.  
  51. FRApp::~FRApp()
  52. {
  53.     UInt16 usCount;
  54.  
  55.     SafeDelete(m_pCareer);
  56.  
  57.     SafeDeleteA(m_aTrackNodes);
  58.     SafeDeleteA(m_aTempTrackNodes);
  59.     SafeDeleteA(m_aAINodes);
  60.     SafeDeleteA(m_aTempAINodes);
  61.  
  62.     for(usCount = 0; usCount < 4; usCount++)
  63.         SafeDelete(m_apPowerUpIcons[usCount]);
  64.  
  65.     for(usCount = 0; usCount < NUM_TRACKS; usCount++)
  66.         SafeDelete(m_apTrackImages[usCount]);
  67.  
  68.     SafeDelete(m_pTacho);
  69.  
  70.     SafeDelete(m_pMenuBackground);
  71. }
  72.  
  73. void FRApp::Prepare(Char* pcCommandLine)
  74. {
  75.     m_usScreenWidth = 640;
  76.     m_usScreenHeight = 480;
  77.  
  78. #if TE_PLATFORM == TE_WIN32
  79.     m_usScreenBpp = 32;
  80. #else
  81.     m_usScreenBpp = 0;
  82. #endif
  83.  
  84.     m_usMirrorWidth = 300;
  85.     m_usMirrorHeight = 75;
  86.  
  87.     m_ulTachoSpeed = 0;
  88.     m_ulCountdown = 0;
  89.     m_bShowAbortMenu = false;
  90.     m_fCamDelta= 0;
  91.     m_ServerPassword = "";
  92.     m_bCareerRace = false;
  93.     m_usDifficulty = 2;
  94. }
  95.  
  96. void FRApp::Start(void)
  97. {
  98.     TEString Name;
  99.     TEVector Center;
  100.  
  101.     Name = "funracing.maps";
  102.     TEFileManager::GetFileManager()->AddArchive(Name);
  103.     Name = "funracing.models";
  104.     TEFileManager::GetFileManager()->AddArchive(Name);
  105.     Name = "funracing.textures";
  106.     TEFileManager::GetFileManager()->AddArchive(Name);
  107.  
  108.     Name = "Fun Racing";
  109.     m_pRenderer->SetWindowTitle(Name);
  110.  
  111.     m_pTimer->SetTimeFactor(0.0f);
  112.  
  113.     LoadConfig();
  114.     m_pRenderer->SetResolution(m_usScreenWidth, m_usScreenHeight, m_usScreenBpp);
  115.     ApplyDetailSettings();
  116.     LoadRes();
  117.     m_pSoundDevice->SetVolume(m_fGeneralVolume);
  118.  
  119.     m_pTimer->SetTimeFactor(1.0f);
  120.  
  121.     if(m_bPlayIntro)
  122.     {
  123.         m_GameState = PLAYING_INTROS;
  124.         
  125.         FREngineLogo::Start();
  126.         FRGameLogo::Start();
  127.     }
  128.     
  129.     // make sure no outdated keydown messages arrive in main menu
  130.     m_GameState = NOTREADY;
  131.     m_pInputDevices->Update();
  132.  
  133.     m_pEngine->ShowCursor(true);
  134.     m_GameState = MAINMENU;
  135. }
  136.  
  137. void FRApp::Update1(UInt32 ulDeltaT)
  138. {
  139.     if((m_GameState == RACE || m_GameState == SERVERRACE || m_GameState == CLIENTRACE) &&
  140.         TEConsole::GetConsole()->GetState() == TE_CONSOLE_HIDE)
  141.         UpdateRace1(ulDeltaT);
  142. }
  143.  
  144. void FRApp::Update2(UInt32 ulDeltaT)
  145. {
  146.     if((m_GameState == RACE || m_GameState == SERVERRACE || m_GameState == CLIENTRACE) &&
  147.         TEConsole::GetConsole()->GetState() == TE_CONSOLE_HIDE)
  148.         UpdateRace2(ulDeltaT);
  149. }
  150.  
  151. void FRApp::Render(void)
  152. {
  153.     if(m_GameState == RACE || m_GameState == SERVERRACE || m_GameState == CLIENTRACE)
  154.     {
  155.         RenderRace();
  156.     }
  157.     else if(m_GameState == MAINMENU)
  158.         RenderMainMenu();
  159.     else if(m_GameState == OPTIONSMENU)
  160.         RenderOptionsMenu();
  161.     else if(m_GameState == VIDEOMENU)
  162.         RenderVideoMenu();
  163.     else if(m_GameState == AUDIOMENU)
  164.         RenderAudioMenu();
  165.     else if(m_GameState == INPUTMENU1)
  166.         RenderInputMenu1();
  167.     else if(m_GameState == INPUTMENU2)
  168.         RenderInputMenu2();
  169.     else if(m_GameState == INPUTMENU3)
  170.         RenderInputMenu3();
  171.     else if(m_GameState == CAREERMENU)
  172.         RenderCareerMenu();
  173.     else if(m_GameState == CAREERRACEMENU)
  174.         RenderCareerRaceMenu();
  175.     else if(m_GameState == QUICKRACEMENU)
  176.         RenderQuickRaceMenu();
  177.     else if(m_GameState == NETWORKMENU)
  178.         RenderNetworkMenu();
  179.     else if(m_GameState == SERVERMENU)
  180.         RenderServerMenu();
  181.     else if(m_GameState == CLIENTMENU)
  182.         RenderClientMenu();
  183.     else if(m_GameState == WAITINGFORCLIENTS)
  184.         RenderWaitingForClients();
  185.     else if(m_GameState == WAITINGFORSERVER)
  186.         RenderWaitingForServer();
  187.     else if(m_GameState == CREDITS)
  188.         RenderCredits();
  189.     else if(m_GameState == STATISTIC)
  190.         RenderStatistic();
  191. }
  192.  
  193. void FRApp::KeyDown(TEKeyState ulKey)
  194. {
  195.     if(m_GameState == RACE || m_GameState == SERVERRACE || m_GameState == CLIENTRACE)
  196.     {
  197.         if(m_bShowAbortMenu)
  198.         {
  199.             if(m_GameState == SERVERRACE)
  200.             {
  201.                 KeyDownInGameMenuServer(ulKey);
  202.                 return;
  203.             }
  204.             else if(m_GameState == CLIENTRACE)
  205.             {
  206.                 KeyDownInGameMenuClient(ulKey);
  207.                 return;
  208.             }
  209.         }
  210.  
  211.         if(ulKey == TE_KEY_ESCAPE)
  212.         {
  213.             if(m_pCar->m_State != RACING && m_pCar->m_State != WAITING && m_GameState == RACE)
  214.             {
  215.                 if(m_bCareerRace)
  216.                 {
  217.                     UInt32 ulCount, ulCount2, aulPos[4];
  218.  
  219.                     m_pCareer->ulCurrRace++;
  220.  
  221.                     aulPos[0] = 0;
  222.                     aulPos[1] = 1;
  223.                     aulPos[2] = 2;
  224.                     aulPos[3] = 3;
  225.  
  226.                     for(ulCount = 0; ulCount < 3; ulCount++)
  227.                     {
  228.                         for(ulCount2 = ulCount+1; ulCount2 < 4; ulCount2++)
  229.                         {
  230.                             bool bChange = false;
  231.                             bool bFin1 = m_apCars[aulPos[ulCount]]->m_State >= FINISHED1ST && m_apCars[aulPos[ulCount]]->m_State <= FINISHED4TH;
  232.                             bool bFin2 = m_apCars[aulPos[ulCount2]]->m_State >= FINISHED1ST && m_apCars[aulPos[ulCount2]]->m_State <= FINISHED4TH;
  233.  
  234.                             TEAssert(m_apCars[aulPos[ulCount]]->m_State != m_apCars[aulPos[ulCount2]]->m_State);
  235.  
  236.                             if(bFin1 && bFin2)
  237.                             {
  238.                                 if(m_apCars[aulPos[ulCount]]->m_State > m_apCars[aulPos[ulCount2]]->m_State)
  239.                                     bChange = true;
  240.                             }
  241.                             else if(bFin2) bChange = true;
  242.                             else if(!bFin1 && !bFin2)
  243.                             {
  244.                                 if(m_apCars[aulPos[ulCount]]->m_State == DESTROYED && m_apCars[aulPos[ulCount2]]->m_State != DESTROYED)
  245.                                     bChange = true;
  246.                                 else if(m_apCars[aulPos[ulCount]]->m_ulLap < m_apCars[aulPos[ulCount2]]->m_ulLap)
  247.                                     bChange = true;
  248.                                 else if(m_apCars[aulPos[ulCount]]->m_ulLap == m_apCars[aulPos[ulCount2]]->m_ulLap)
  249.                                 {
  250.                                     if( (m_apCars[aulPos[ulCount]]->m_ulTrackNode-1 < m_apCars[aulPos[ulCount2]]->m_ulTrackNode-1))
  251.                                         bChange = true;
  252.                                     else if(m_apCars[aulPos[ulCount]]->m_ulTrackNode == m_apCars[aulPos[ulCount2]]->m_ulTrackNode)
  253.                                     {
  254.                                         Float fDist1 = m_aTrackNodes[m_apCars[aulPos[ulCount]]->m_ulTrackNode].m_Plane.DistanceToPlane(m_apCars[aulPos[ulCount]]->m_Center);
  255.                                         Float fDist2 = m_aTrackNodes[m_apCars[aulPos[ulCount2]]->m_ulTrackNode].m_Plane.DistanceToPlane(m_apCars[aulPos[ulCount2]]->m_Center);
  256.  
  257.                                         if(fDist1 > fDist2) bChange = true;
  258.                                     }
  259.                                 }
  260.                             }
  261.  
  262.                             if(bChange)
  263.                             {
  264.                                 UInt32 ulTmp = aulPos[ulCount];
  265.  
  266.                                 aulPos[ulCount] = aulPos[ulCount2];
  267.                                 aulPos[ulCount2] = ulTmp;
  268.                             }
  269.                         }
  270.                     }
  271.  
  272.                     for(ulCount = 0; ulCount < 4; ulCount++)
  273.                         m_pCareer->aulDriverPlacement[aulPos[ulCount]] = ulCount;
  274.  
  275.                     for(ulCount = 0; ulCount < 4; ulCount++)
  276.                     {
  277.                         if(m_pCareer->aulDriverPlacement[ulCount] == 0)
  278.                             m_pCareer->aulDriverScore[ulCount] += 10;
  279.                         else if(m_pCareer->aulDriverPlacement[ulCount] == 1)
  280.                             m_pCareer->aulDriverScore[ulCount] += 8;
  281.                         else if(m_pCareer->aulDriverPlacement[ulCount] == 2)
  282.                             m_pCareer->aulDriverScore[ulCount] += 6;
  283.                         else m_pCareer->aulDriverScore[ulCount] += 4;
  284.                     }
  285.  
  286.                     ExitRace();
  287.  
  288.                     if(m_pCareer->ulCurrRace < 10)
  289.                         SaveCareer();
  290.  
  291.                     m_GameState = STATISTIC;
  292.                 }
  293.                 else ExitRace();
  294.             }
  295.             else
  296.             {
  297.                 m_bShowAbortMenu = !m_bShowAbortMenu;
  298.  
  299.                 if(m_GameState != RACE) m_pEngine->ShowCursor(true);
  300.             }
  301.         }
  302.         else if(ulKey == TE_KEY_ENTER && m_bShowAbortMenu && m_GameState == RACE)
  303.             ExitRace();
  304.         else if(ulKey == m_aulKeys[RESET] && m_pCar->m_State == RACING)
  305.         {
  306.             UInt32 ulTmp;
  307.  
  308.             ulTmp = m_pCar->m_ulTrackNode;
  309.  
  310.             if(ulTmp == 0)
  311.                 ulTmp = m_ulNumTrackNodes-1;
  312.             else ulTmp--;
  313.  
  314.             if(ulTmp == 0)
  315.                 m_pCar->m_ulLap--;
  316.  
  317.             m_pCar->Reset(m_aTrackNodes[ulTmp].m_Position, m_aTrackNodes[ulTmp].m_Plane.m_Normal);
  318.  
  319.             if(m_GameState == CLIENTRACE)
  320.             {
  321.                 ulTmp = FRCLIENTRESET;
  322.                 m_pNetworkManager->SendDataToServer(&ulTmp, sizeof(ulTmp));
  323.             }
  324.             else if(m_GameState == SERVERRACE)
  325.             {
  326.                 FRCarEnable Enable;
  327.  
  328.                 Enable.ulMsgType = FRBLINKING;
  329.                 Enable.ucCar = 0;
  330.                 m_pNetworkManager->SendDataToAllClients(&Enable, sizeof(Enable));
  331.             }
  332.         }
  333.         else if(ulKey == m_aulKeys[SCREENSHOT])
  334.         {
  335.             Char acTmp[128];
  336.             TEString Name;
  337.  
  338.             sprintf(acTmp, "%d",m_pTimer->GetRealTime());
  339.             Name.Set(acTmp);
  340.  
  341.             m_pRenderer->TakeScreenshot(Name);
  342.         }
  343.         else if(ulKey == m_aulKeys[CAMPOS])
  344.         {
  345.             m_ulCurrCamPos++;
  346.  
  347.             if(m_ulCurrCamPos > 2)
  348.                 m_ulCurrCamPos = 0;
  349.             
  350.             m_fCamDelta= 0;
  351.         }
  352.         else if(ulKey == m_aulKeys[POWERUP])
  353.         {
  354.             if(m_GameState == CLIENTRACE)
  355.             {
  356.                 UInt32 ulTmp = FRCLIENTPOWERUP;
  357.                 m_pNetworkManager->SendDataToServer(&ulTmp, sizeof(ulTmp));
  358.             }
  359.             else if(m_GameState == SERVERRACE)
  360.             {
  361.                 FRCarEnable Enable;
  362.  
  363.                 Enable.ulMsgType = FRENABLEPOWERUP;
  364.                 Enable.ucCar = 0;
  365.                 m_pNetworkManager->SendDataToAllClients(&Enable, sizeof(Enable));
  366.                 
  367.                 m_pCar->EnablePowerUp();
  368.             }
  369.             else m_pCar->EnablePowerUp();
  370.         }
  371.         else if(ulKey == m_aulKeys[HORN])
  372.         {
  373.             m_pCar->Horn();
  374.  
  375.             if(m_GameState == CLIENTRACE)
  376.             {
  377.                 UInt32 ulTmp = FRCLIENTHORN;
  378.                 m_pNetworkManager->SendDataToServer(&ulTmp, sizeof(ulTmp));
  379.             }
  380.             else if(m_GameState == SERVERRACE)
  381.             {
  382.                 FRCarEnable Enable;
  383.  
  384.                 Enable.ulMsgType = FRENABLEHORN;
  385.                 Enable.ucCar = 0;
  386.                 m_pNetworkManager->SendDataToAllClients(&Enable, sizeof(Enable));
  387.             }
  388.         }
  389.     }
  390.     else if(m_GameState == MAINMENU)
  391.         KeyDownMainMenu(ulKey);
  392.     else if(m_GameState == OPTIONSMENU)
  393.         KeyDownOptionsMenu(ulKey);
  394.     else if(m_GameState == VIDEOMENU)
  395.         KeyDownVideoMenu(ulKey);
  396.     else if(m_GameState == AUDIOMENU)
  397.         KeyDownAudioMenu(ulKey);
  398.     else if(m_GameState == INPUTMENU1)
  399.         KeyDownInputMenu1(ulKey);
  400.     else if(m_GameState == INPUTMENU2)
  401.         KeyDownInputMenu2(ulKey);
  402.     else if(m_GameState == INPUTMENU3)
  403.         KeyDownInputMenu3(ulKey);
  404.     else if(m_GameState == CAREERMENU)
  405.         KeyDownCareerMenu(ulKey);
  406.     else if(m_GameState == CAREERRACEMENU)
  407.         KeyDownCareerRaceMenu(ulKey);
  408.     else if(m_GameState == QUICKRACEMENU)
  409.         KeyDownQuickRaceMenu(ulKey);
  410.     else if(m_GameState == NETWORKMENU)
  411.         KeyDownNetworkMenu(ulKey);
  412.     else if(m_GameState == SERVERMENU)
  413.         KeyDownServerMenu(ulKey);
  414.     else if(m_GameState == CLIENTMENU)
  415.         KeyDownClientMenu(ulKey);
  416.     else if(m_GameState == STATISTIC)
  417.         KeyDownStatistic(ulKey);
  418. }
  419. void FRApp::KeyUp(TEKeyState ulKey)
  420. {
  421. }
  422.  
  423. void FRApp::MouseMovement(UInt32 ulPosX, UInt32 ulPosY, Int32 lMovX, Int32 lMovY, Char cWheel)
  424. {
  425. }
  426.  
  427. void FRApp::JoystickMovement(Int32 lX, Int32 lY, Int32 lZ)
  428. {
  429. }
  430.  
  431. void FRApp::Terminate(void)
  432. {
  433. }
  434.  
  435. bool FRApp::ReceiveCustomEntity(TECustomEntity* pEntity)
  436. {
  437.     TEEngineObject* pObj;
  438.     Int32 lPos;
  439.  
  440.     if(pEntity->m_Name == "TrackNode")
  441.     {
  442.         lPos = (Int32) *pEntity->m_acData;
  443.  
  444.         if(lPos >= 0 && lPos < MAX_NODES)
  445.         {
  446.             m_aTempTrackNodes[lPos].m_Position = pEntity->m_Position;
  447.             m_aTempTrackNodes[lPos].m_Plane = *pEntity->m_pPolygonList->GetPlanes();
  448.             m_aTempTrackNodes[lPos].m_BSphere.UpdateVolume(pEntity->m_pPolygonList, true);
  449.             m_aTempTrackNodes[lPos].m_BSphere.SetData(pEntity->m_Position, 900.0f);
  450.             m_ulNumTrackNodes++;
  451.         }
  452.     }
  453.     else if(pEntity->m_Name == "AINode")
  454.     {
  455.         lPos = (Int32) *pEntity->m_acData;
  456.  
  457.         if(lPos >= 0 && lPos < MAX_NODES)
  458.         {
  459.             m_aTempAINodes[lPos].m_Position = pEntity->m_Position;
  460.             m_aTempAINodes[lPos].m_fMaxSpeed =  *((Float*)(pEntity->m_acData+4));
  461.             m_aTempAINodes[lPos].m_bHandbrake =  *((bool*)(pEntity->m_acData+8));
  462.             m_ulNumAINodes++;
  463.         }
  464.     }
  465.     else if(pEntity->m_Name == "StartPosition")
  466.     {
  467.         lPos = (Int32) *pEntity->m_acData;
  468.  
  469.         if(lPos >= 1 && lPos <= 4)
  470.         {
  471.             lPos = lPos-1;
  472.             m_aStartPositions[lPos] = pEntity->m_Position;
  473.             m_aStartRotations[lPos] =  *((Float*)(pEntity->m_acData+4));
  474.         }
  475.     }
  476.     else if(pEntity->m_Name == "Barrier")
  477.     {
  478.         pObj = new FRBarrier(pEntity);
  479.         TEEngine::GetEngine()->AddObjectToWorld(pObj);
  480.     }
  481.     else if(pEntity->m_Name == "PowerUp" && FRCar::ms_bPowerUpsEnabled)
  482.     {
  483.         pObj = new FRPowerUp(pEntity->m_Position);
  484.         TEEngine::GetEngine()->AddObjectToWorld(pObj);
  485.     }
  486.     else if(pEntity->m_Name == "RoadSign" && m_Details != VERYLOW)
  487.     {
  488.         pObj = new FRRoadSign(pEntity);
  489.         TEEngine::GetEngine()->AddObjectToWorld(pObj);
  490.     }
  491.  
  492.     return false;
  493. }
  494.  
  495. void FRApp::NewClientConnected(TEClient* pClient)
  496. {
  497.     FRGameInfo GameInfo;
  498.     
  499.     m_apClients[m_ulNumClients] = pClient;
  500.     m_ulNumClients++;
  501.  
  502.     GameInfo.ulMsgType = FRGAMEINFO;
  503.     GameInfo.GameType = m_CurrGameType;
  504.     GameInfo.ulTrack = m_ulCurrTrack;
  505.     GameInfo.ulNumLaps = m_ulNumLapsForCurrRace;
  506.  
  507.     m_pNetworkManager->SendDataToClient(pClient->ulID, &GameInfo, sizeof(GameInfo));
  508. }
  509.  
  510. void FRApp::ClientDisconnected(TEClient* pClient)
  511. {
  512.     TEString Msg = pClient->acName;
  513.     TEClient* apClients[3];
  514.     FRCarName aClientCars[3];
  515.     UInt32 ulCount, ulIndex;
  516.  
  517.     if(m_GameState == WAITINGFORCLIENTS)
  518.     {
  519.         memcpy(apClients, m_apClients, sizeof(TEClient*)*3);
  520.         memcpy(aClientCars, m_aClientCars, sizeof(FRCarName)*3);
  521.         memset(m_apClients, 0, sizeof(TEClient*)*3);
  522.         memset(m_aClientCars, 0, sizeof(FRCarName)*3);
  523.         
  524.         ulCount = ulIndex = 0;
  525.         
  526.         for(; ulCount < m_ulNumClients; ulCount++)
  527.         {
  528.             if(apClients[ulCount] != pClient)
  529.             {
  530.                 m_apClients[ulIndex] = apClients[ulCount];
  531.                 m_aClientCars[ulIndex] = aClientCars[ulCount];
  532.                 ulIndex++;
  533.             }
  534.         }
  535.         
  536.         m_ulNumClients -= 1;
  537.     }
  538.     else
  539.     {
  540.         for(ulCount = 0; ulCount < m_ulNumClients; ulCount++)
  541.         {
  542.             if(m_apClients[ulCount] == pClient)
  543.                 m_apClients[ulCount] = NULL;
  544.         }
  545.     }
  546.  
  547.     Msg = Msg + TETranslator::GetTranslator()->Translate(" left the game");
  548.     
  549.     TEConsole::GetConsole()->ConsoleMessage(Msg, TE_USER_ONLY);
  550. }
  551.  
  552. void FRApp::DataFromClient(TEClient* pClient, Char* pData, UInt32 ulSize)
  553. {
  554.     UInt32 ulTmp = *(UInt32*) pData;
  555.     UInt32 ulClient = GetClientPos(pClient);
  556.     FRClientCar* pCar;
  557.     FRClientState* pState;
  558.     FRCarEnable Enable;
  559.  
  560.     switch(ulTmp){
  561.     case FRCLIENTCAR:
  562.         if(ulSize != sizeof(FRClientCar))
  563.         {
  564.             TEString Error = "Network Message Size Incorrect";
  565.             TEAddErrorLog(Error);
  566.             return;
  567.         }
  568.  
  569.         pCar = (FRClientCar*) pData;
  570.         m_aClientCars[ulClient] = pCar->Car;
  571.         break;
  572.     case FRCLIENTSTATE:
  573.         if(ulSize != sizeof(FRClientState))
  574.         {
  575.             TEString Error = "Network Message Size Incorrect";
  576.             TEAddErrorLog(Error);
  577.             return;
  578.         }
  579.  
  580.         pState = (FRClientState*) pData;
  581.         m_apCars[1+ulClient]->SetPedal(pState->fGasPedal);
  582.         m_apCars[1+ulClient]->SetSteeringWheel(pState->fSteeringWheel);
  583.         m_apCars[1+ulClient]->SetHandbrake(pState->bHandbrake);
  584.         break;
  585.     case FRCLIENTRESET:
  586.         if(ulSize != sizeof(UInt32))
  587.         {
  588.             TEString Error = "Network Message Size Incorrect";
  589.             TEAddErrorLog(Error);
  590.             return;
  591.         }
  592.  
  593.         UInt32 ulTmp;
  594.         
  595.         ulTmp = m_apCars[1+ulClient]->m_ulTrackNode;
  596.         
  597.         if(ulTmp == 0)
  598.             ulTmp = m_ulNumTrackNodes-1;
  599.         else ulTmp--;
  600.  
  601.         if(ulTmp == 0)
  602.             m_apCars[1+ulClient]->m_ulLap--;
  603.  
  604.         m_apCars[1+ulClient]->Reset(m_aTrackNodes[ulTmp].m_Position, m_aTrackNodes[ulTmp].m_Plane.m_Normal);
  605.  
  606.         Enable.ulMsgType = FRBLINKING;
  607.         Enable.ucCar = (UChar) (1 + ulClient);
  608.         m_pNetworkManager->SendDataToAllClients(&Enable, sizeof(Enable));
  609.         break;
  610.     case FRCLIENTPOWERUP:
  611.         if(ulSize != sizeof(UInt32))
  612.         {
  613.             TEString Error = "Network Message Size Incorrect";
  614.             TEAddErrorLog(Error);
  615.             return;
  616.         }
  617.  
  618.         m_apCars[1+ulClient]->EnablePowerUp();
  619.         Enable.ulMsgType = FRENABLEPOWERUP;
  620.         Enable.ucCar = (UChar) (1 + ulClient);
  621.         m_pNetworkManager->SendDataToAllClients(&Enable, sizeof(Enable));
  622.         break;
  623.     case FRCLIENTHORN:
  624.         if(ulSize != sizeof(UInt32))
  625.         {
  626.             TEString Error = "Network Message Size Incorrect";
  627.             TEAddErrorLog(Error);
  628.             return;
  629.         }
  630.  
  631.         m_apCars[1+ulClient]->Horn();
  632.         Enable.ulMsgType = FRENABLEHORN;
  633.         Enable.ucCar = (UChar) (1 + ulClient);
  634.         m_pNetworkManager->SendDataToAllClients(&Enable, sizeof(Enable));
  635.         break;
  636.     case FRCLIENTREADY:
  637.         if(ulSize != sizeof(UInt32))
  638.         {
  639.             TEString Error = "Network Message Size Incorrect";
  640.             TEAddErrorLog(Error);
  641.             return;
  642.         }
  643.  
  644.         m_abClientReady[ulClient] = true;
  645.         break;
  646.     };
  647. }
  648.  
  649. void FRApp::ServerConnected(Char acServerName[32])
  650. {
  651.     m_bConnectedToServer = true;
  652. }
  653.  
  654. void FRApp::ServerDisconnected(void)
  655. {
  656.     m_bConnectedToServer = false;
  657.  
  658.     if(m_GameState == CLIENTRACE)
  659.     {
  660.         UnloadBSPFile();
  661.         m_GameState = MAINMENU;
  662.         m_pNetworkManager->EndClient();
  663.         m_pEngine->ShowCursor(true);
  664.     }
  665. }
  666.  
  667. void FRApp::DataFromServer(Char* pData, UInt32 ulSize)
  668. {
  669.     UInt32 ulMsgType = *(UInt32*) pData;
  670.     UInt32 ulCount, *pulData;
  671.     FRGameInfo* pInfo;
  672.     FRPlayerInfo* pInfo2;
  673.     FRCarUpdate* pUpdate;
  674.     FRCarEnable* pEnable;
  675.     FRCountdown* pCountdown;
  676.     FRClientCar Car;
  677.     TEString Str;
  678.  
  679.     switch(ulMsgType){
  680.     case FRGAMEINFO:
  681.         if(ulSize != sizeof(FRGameInfo))
  682.         {
  683.             TEString Error = "Network Message Size Incorrect";
  684.             TEAddErrorLog(Error);
  685.             return;
  686.         }
  687.  
  688.         pInfo = (FRGameInfo*) pData;
  689.         m_CurrGameType = pInfo->GameType;
  690.         m_ulCurrTrack = pInfo->ulTrack;
  691.         m_ulNumLapsForCurrRace = pInfo->ulNumLaps;
  692.         m_bCareerRace = false;
  693.         m_bShowAbortMenu = false;
  694.         LoadCurrTrack();
  695.         Car.ulMsgType = FRCLIENTCAR;
  696.         Car.Car = m_CurrCar;
  697.         m_pNetworkManager->SendDataToServer(&Car, sizeof(Car));
  698.  
  699.         ulCount = FRCLIENTREADY;
  700.         m_pNetworkManager->SendDataToServer(&ulCount, sizeof(ulCount));
  701.  
  702.         m_GameState = WAITINGFORSERVER;
  703.         m_bConnectedToServer = true;
  704.         m_pEngine->ShowCursor(true);
  705.         break;
  706.     case FRPLAYERINFO:
  707.         if(ulSize != sizeof(FRPlayerInfo))
  708.         {
  709.             TEString Error = "Network Message Size Incorrect";
  710.             TEAddErrorLog(Error);
  711.             return;
  712.         }
  713.  
  714.         pInfo2 = (FRPlayerInfo*) pData;
  715.         
  716.         memset(m_apCars, 0, sizeof(FRCar*) * 4);
  717.         
  718.         for(ulCount = 0; ulCount < pInfo2->ulNumPlayers; ulCount++)
  719.         {
  720.             m_apCars[ulCount] = GetCar(pInfo2->aCars[ulCount], m_aStartPositions[3-ulCount], m_aStartRotations[3-ulCount]);
  721.  
  722.             m_apCars[ulCount]->m_Type = NETWORK;
  723.             m_apCars[ulCount]->m_DriverName = pInfo2->aPlayerNames[ulCount];
  724.             m_pEngine->AddObjectToWorld(m_apCars[ulCount]);
  725.         }
  726.         
  727.         TETextureManager::GetTextureManager()->ReleaseUnusedTextures();
  728.         TEModelManager::GetModelManager()->FreeUnusedModels();
  729.         TESoundManager::GetSoundManager()->FreeUnusedSounds();
  730.  
  731.         m_pCar = m_apCars[pInfo2->ulOwnPos];
  732.         m_pEngine->ShowCursor(false);
  733.         m_bShowAbortMenu = false;
  734.         break;
  735.     case FRCOUNTDOWN:
  736.         if(ulSize != sizeof(FRCountdown))
  737.         {
  738.             TEString Error = "Network Message Size Incorrect";
  739.             TEAddErrorLog(Error);
  740.             return;
  741.         }
  742.  
  743.         pCountdown = (FRCountdown*) pData;
  744.         m_ulCountdown = pCountdown->ucState;
  745.  
  746.         m_GameState = CLIENTRACE;
  747.         break;
  748.     case FRCARUPDATE:
  749.         if(ulSize != sizeof(FRCarUpdate))
  750.         {
  751.             TEString Error = "Network Message Size Incorrect";
  752.             TEAddErrorLog(Error);
  753.             return;
  754.         }
  755.  
  756.         pUpdate = (FRCarUpdate*) pData;
  757.  
  758.         m_apCars[pUpdate->ucCar]->SetPedal(pUpdate->fGasPedal);
  759.         m_apCars[pUpdate->ucCar]->SetSteeringWheel(pUpdate->fSteeringWheel);
  760.         m_apCars[pUpdate->ucCar]->SetHandbrake(pUpdate->bHandbrake);
  761.         m_apCars[pUpdate->ucCar]->m_lCurrentGear = pUpdate->lGear;
  762.         m_apCars[pUpdate->ucCar]->m_lPowerUp = pUpdate->lPowerUp;
  763.         m_apCars[pUpdate->ucCar]->m_Velocity = pUpdate->Velocity;
  764.         m_apCars[pUpdate->ucCar]->m_State = pUpdate->State;
  765.         m_apCars[pUpdate->ucCar]->m_ulLap = pUpdate->ulLap;
  766.  
  767.         if(m_apCars[pUpdate->ucCar]->m_Center != pUpdate->Pos ||
  768.             m_apCars[pUpdate->ucCar]->m_Rotation != pUpdate->Rotation)
  769.         {
  770.             TEAABoundingBox BBox;
  771.             TEVector Min, Max;
  772.             TEOBoundingBox* pBox = (TEOBoundingBox*) m_apCars[pUpdate->ucCar]->m_pBoundingVolume;
  773.  
  774.             m_apCars[pUpdate->ucCar]->m_Center = pUpdate->Pos;
  775.             m_apCars[pUpdate->ucCar]->m_Rotation = pUpdate->Rotation;
  776.  
  777.             BBox = m_apCars[pUpdate->ucCar]->m_pModelRef->GetModelBBox();
  778.             BBox.GetData(Min, Max);
  779.             pBox->SetData(m_apCars[pUpdate->ucCar]->m_Center, Min, Max, m_apCars[pUpdate->ucCar]->m_Rotation);
  780.             m_apCars[pUpdate->ucCar]->UpdateVectors();
  781.         }
  782.  
  783.         break;
  784.     case FRENABLEHORN:
  785.         if(ulSize != sizeof(FRCarEnable))
  786.         {
  787.             TEString Error = "Network Message Size Incorrect";
  788.             TEAddErrorLog(Error);
  789.             return;
  790.         }
  791.  
  792.         pEnable = (FRCarEnable*) pData;
  793.         m_apCars[pEnable->ucCar]->Horn();
  794.         break;
  795.     case FRENABLEPOWERUP:
  796.         if(ulSize != sizeof(FRCarEnable))
  797.         {
  798.             TEString Error = "Network Message Size Incorrect";
  799.             TEAddErrorLog(Error);
  800.             return;
  801.         }
  802.  
  803.         pEnable = (FRCarEnable*) pData;
  804.         m_apCars[pEnable->ucCar]->EnablePowerUp();
  805.         break;
  806.     case FRPLACES:
  807.         if(ulSize != sizeof(UInt32)*5)
  808.         {
  809.             TEString Error = "Network Message Size Incorrect";
  810.             TEAddErrorLog(Error);
  811.             return;
  812.         }
  813.  
  814.         pulData = (UInt32*) pData;
  815.         m_aulPosition[0] = pulData[1];
  816.         m_aulPosition[1] = pulData[2];
  817.         m_aulPosition[2] = pulData[3];
  818.         m_aulPosition[3] = pulData[4];
  819.         break;
  820.     case FRBLINKING:
  821.         if(ulSize != sizeof(FRCarEnable))
  822.         {
  823.             TEString Error = "Network Message Size Incorrect";
  824.             TEAddErrorLog(Error);
  825.             return;
  826.         }
  827.  
  828.         pEnable = (FRCarEnable*) pData;
  829.         m_apCars[pEnable->ucCar]->m_ulLastReset = m_pTimer->GetTime();
  830.         m_apCars[pEnable->ucCar]->m_Visibility = BLINKING;
  831.         break;
  832.     };
  833. }
  834.  
  835. void FRApp::UpdateRace1(UInt32 ulDeltaT)
  836. {
  837.     if(m_pCar->m_State != RACING)
  838.         return;
  839.  
  840.     Float fPedal, fWheel;
  841.     bool bHandbrake;
  842.  
  843.     if(m_GameState == CLIENTRACE)
  844.     {
  845.         fPedal = m_pCar->m_fPedal;
  846.         fWheel = m_pCar->m_fSteeringWheel;
  847.         bHandbrake = m_pCar->m_bHandbrake;
  848.     }
  849.  
  850.     if(m_pInputDevices->IsPressed(m_aulKeys[GAS]))
  851.         m_pCar->SetPedal(1.0f);
  852.     else if(m_pInputDevices->IsPressed(m_aulKeys[BRAKE]))
  853.         m_pCar->SetPedal(-1.0f);
  854.     else m_pCar->SetPedal(0.0f);
  855.  
  856.     if(m_pInputDevices->IsPressed(m_aulKeys[RIGHT]))
  857.         m_pCar->SetSteeringWheel(1.0f);
  858.     else if(m_pInputDevices->IsPressed(m_aulKeys[LEFT]))
  859.         m_pCar->SetSteeringWheel(-1.0f);
  860.     else m_pCar->SetSteeringWheel(0.0f);
  861.  
  862.     if(m_pInputDevices->IsPressed(m_aulKeys[HANDBRAKE]))
  863.         m_pCar->SetHandbrake(true);
  864.     else m_pCar->SetHandbrake(false);
  865.  
  866.     if(m_bUseJoystick)
  867.     {
  868.         Int32 lX, lY, lZ;
  869.         Float fTmp;
  870.  
  871.         m_pInputDevices->GetJoystickAxis(lX, lY, lZ);
  872.  
  873.         fTmp = lX * m_fJoystickSensitivity * 0.001f;
  874.  
  875.         if(fTmp < -1.0f)
  876.             fTmp = -1.0f;
  877.         else if(fTmp > 1.0f)
  878.             fTmp = 1.0f;
  879.         else if(TEAbs(fTmp) <= 0.05f)
  880.             fTmp = 0.0f;
  881.  
  882.         m_pCar->SetSteeringWheel(fTmp);
  883.  
  884.         if(m_JoystickAccel == YAXIS)
  885.         {
  886.             fTmp = -lY * m_fJoystickSensitivity * 0.001f;
  887.             
  888.             if(fTmp < -1.0f)
  889.                 fTmp = -1.0f;
  890.             else if(fTmp > 1.0f)
  891.                 fTmp = 1.0f;
  892.             else if(TEAbs(fTmp) <= 0.05f)
  893.                 fTmp = 0.0f;
  894.             
  895.             m_pCar->SetPedal(fTmp);
  896.         }
  897.         else if(m_JoystickAccel == ZAXIS)
  898.         {
  899.             fTmp = -lZ * m_fJoystickSensitivity * 0.001f;
  900.             
  901.             if(fTmp < -1.0f)
  902.                 fTmp = -1.0f;
  903.             else if(fTmp > 1.0f)
  904.                 fTmp = 1.0f;
  905.             else if(TEAbs(fTmp) <= 0.05f)
  906.                 fTmp = 0.0f;
  907.             
  908.             m_pCar->SetPedal(fTmp);
  909.         }
  910.     }
  911.  
  912.     if(m_GameState == CLIENTRACE)
  913.     {
  914.         if(fPedal != m_pCar->m_fPedal || fWheel != m_pCar->m_fSteeringWheel ||
  915.             bHandbrake != m_pCar->m_bHandbrake)
  916.         {
  917.             FRClientState State;
  918.  
  919.             State.ulMsgType = FRCLIENTSTATE;
  920.             State.fGasPedal = m_pCar->m_fPedal;
  921.             State.fSteeringWheel = m_pCar->m_fSteeringWheel;
  922.             State.bHandbrake = m_pCar->m_bHandbrake;
  923.  
  924.             m_pNetworkManager->SendDataToServer(&State, sizeof(State));
  925.         }
  926.     }
  927.  
  928.     m_pCar->m_bClip = true;
  929. }
  930.  
  931.  
  932. void FRApp::UpdateRace2(UInt32 ulDeltaT)
  933. {
  934.     TECamera* pCam = m_pRenderer->GetCamera();
  935.     TEVector Center, Rot;
  936.     TEMatrix3x3 MatRot;
  937.     UInt16 usCount, usCmp;
  938.     UInt32 ulTmp;
  939.  
  940.     Center = m_pCar->GetCenter();
  941.     Rot = m_pCar->GetRotation();
  942.  
  943.     if(m_pCar->m_Visibility == INVISIBLE)
  944.         m_pCar->m_Visibility = NORMAL;
  945.  
  946.     if(m_bCamAnimation && m_ulCurrCamPos != 0)
  947.     {
  948.         if(m_pCar->m_fSteeringWheel > 0.0f)
  949.         {
  950.             if(m_fCamDelta < 10.0f)
  951.             {
  952.                 m_fCamDelta += CAM_SPEED * ulDeltaT * 0.001f;
  953.  
  954.                 if(m_fCamDelta > 10.0f)
  955.                     m_fCamDelta = 10.0f;
  956.             }
  957.         }
  958.         else if(m_pCar->m_fSteeringWheel < 0.0f)
  959.         {
  960.             if(m_fCamDelta > -10.0f)
  961.             {
  962.                 m_fCamDelta -= CAM_SPEED * ulDeltaT * 0.001f;
  963.  
  964.                 if(m_fCamDelta < -10.0f)
  965.                     m_fCamDelta = -10.0f;
  966.             }
  967.         }
  968.         else if(m_fCamDelta != 0)
  969.         {
  970.             if(m_fCamDelta > 0.0f)
  971.             {
  972.                 m_fCamDelta -= CAM_SPEED * ulDeltaT * 0.001f;
  973.  
  974.                 if(m_fCamDelta < 0.0f)
  975.                     m_fCamDelta = 0.0f;
  976.             }
  977.             else if(m_fCamDelta < 0.0f)
  978.             {
  979.                 m_fCamDelta += CAM_SPEED * ulDeltaT * 0.001f;
  980.  
  981.                 if(m_fCamDelta > 0.0f)
  982.                     m_fCamDelta = 0.0f;
  983.             }
  984.         }
  985.     }
  986.  
  987.     if(m_pInputDevices->IsNotPressed(m_aulKeys[LOOKBACK]))
  988.     {
  989.         switch(m_ulCurrCamPos){
  990.         case 0:
  991.             Center.m_fY += m_pCar->m_CarSize.m_fY * 0.75f;
  992.             Rot.m_fX = Rot.m_fZ = 0;
  993.             Rot.m_fY = -Rot.m_fY;
  994.             m_pCar->m_Visibility = INVISIBLE;
  995.             m_pCar->m_bClip = false;
  996.             break;
  997.         case 1:
  998.             MatRot.YRotationMatrixDeg(Rot.m_fY);
  999.             Center = Center + MatRot * TEVector(0.0f, 25.0f, -65.0f); 
  1000.             
  1001.             if(m_bCamAnimation && m_fCamDelta != 0)
  1002.                 Center = Center + MatRot * TEVector(m_fCamDelta, 0.0f, 0.0f);
  1003.  
  1004.             Rot.m_fX = -12.5f;
  1005.             Rot.m_fY = -Rot.m_fY;
  1006.             Rot.m_fZ = 0;
  1007.             break;
  1008.         case 2:
  1009.             MatRot.YRotationMatrixDeg(Rot.m_fY);
  1010.             Center = Center + MatRot * TEVector(0.0f, 40.0f, -100.0f); 
  1011.             
  1012.             if(m_bCamAnimation && m_fCamDelta != 0)
  1013.                 Center = Center + MatRot * TEVector(m_fCamDelta, 0.0f, 0.0f);
  1014.  
  1015.             Rot.m_fX = -17.5f;
  1016.             Rot.m_fY = -Rot.m_fY;
  1017.             Rot.m_fZ = 0;
  1018.             break;
  1019.         };
  1020.     }
  1021.     else
  1022.     {
  1023.         MatRot.YRotationMatrixDeg(Rot.m_fY);
  1024.         Center = Center + MatRot * TEVector(0.0f, m_pCar->m_CarSize.m_fY * 0.25f, -m_pCar->m_CarSize.m_fZ * 0.85f);
  1025.         Rot.m_fX = Rot.m_fZ = 0;
  1026.         Rot.m_fY = 180.0f - Rot.m_fY;
  1027.         m_pCar->m_Visibility = INVISIBLE;
  1028.         m_pCar->m_bClip = false;
  1029.     }
  1030.  
  1031.     pCam->SetPosition(Center);
  1032.     pCam->SetRotation(Rot);
  1033.  
  1034.     if(m_GameState == RACE || m_GameState == SERVERRACE)
  1035.     {
  1036.         UInt32 ulCars = 4;
  1037.  
  1038.         if(m_GameState == SERVERRACE)
  1039.             ulCars = 1 + m_ulNumClients;
  1040.  
  1041.         for(usCount = 0; usCount < ulCars; usCount++)
  1042.         {
  1043.             TEVector Center = m_apCars[usCount]->GetCenter();
  1044.             
  1045.             if(m_aTrackNodes[m_apCars[usCount]->m_ulTrackNode].m_Plane.DistanceToPlane(Center) < 0 &&
  1046.                 m_aTrackNodes[m_apCars[usCount]->m_ulTrackNode].m_BSphere.IntersectsVolume(*(TEOBoundingBox*) m_apCars[usCount]->m_pBoundingVolume))
  1047.             {
  1048.                 m_apCars[usCount]->m_ulTrackNode++;
  1049.  
  1050.                 if(m_apCars[usCount]->m_ulTrackNode >= m_ulNumTrackNodes)
  1051.                 {
  1052.                     m_apCars[usCount]->m_ulTrackNode = 0;
  1053.                 }
  1054.                 
  1055.                 if(m_apCars[usCount]->m_ulTrackNode == 1)
  1056.                     m_apCars[usCount]->m_ulLap++;
  1057.             }
  1058.  
  1059.             if(m_apCars[usCount]->m_Type == AI)
  1060.                 DoAI(m_apCars[usCount]);
  1061.  
  1062.             if( (m_apCars[usCount]->m_State >= FINISHED1ST && m_apCars[usCount]->m_State <= FINISHED4TH && m_apCars[usCount]->m_ulTrackNode > 0) ||
  1063.                 m_apCars[usCount]->m_State == KO || m_apCars[usCount]->m_State == DESTROYED)
  1064.             {
  1065.                 if(m_apCars[usCount]->m_Velocity.GetLength() * 0.36f > 35 && m_apCars[usCount]->m_lCurrentGear > REVERSE_GEAR &&
  1066.                     m_apCars[usCount]->m_Velocity.DotProduct(m_apCars[usCount]->m_Forward) >= 0)
  1067.                 {
  1068.                     m_apCars[usCount]->SetPedal(-1.0f);
  1069.                     m_apCars[usCount]->m_lCurrentGear = SECOND_GEAR;
  1070.                 }
  1071.                 else
  1072.                 {
  1073.                     m_apCars[usCount]->SetPedal(0.0f);
  1074.                     m_apCars[usCount]->m_lCurrentGear = NEUTRAL_GEAR;
  1075.                     m_apCars[usCount]->m_fCurrentRPM = 1000.0f;
  1076.                     m_apCars[usCount]->m_Velocity = TEVector(0.0f, 0.0f, 0.0f);
  1077.                     m_apCars[usCount]->m_fElasticity = 0.3f;
  1078.                     m_apCars[usCount]->m_fFrictionFactor = 0.5f;
  1079.                 }
  1080.                 m_apCars[usCount]->SetHandbrake(true);
  1081.                 m_apCars[usCount]->SetSteeringWheel(0.0f);
  1082.                 m_apCars[usCount]->m_fBrakeEfficiency = 25.0f;
  1083.             }
  1084.         }
  1085.  
  1086.         for(usCount = 0; usCount < ulCars-1; usCount++)
  1087.         {
  1088.             if(m_apCars[m_aulPosition[usCount]]->m_State == RACING || m_apCars[m_aulPosition[usCount]]->m_State == DESTROYED)
  1089.             {
  1090.                 for(usCmp = usCount+1; usCmp < ulCars; usCmp++)
  1091.                 {
  1092.                     if(m_apCars[m_aulPosition[usCmp]]->m_State == RACING)
  1093.                     {
  1094.                         UInt32 ulLap1, ulLap2;
  1095.  
  1096.                         ulLap1 = m_apCars[m_aulPosition[usCmp]]->m_ulLap;
  1097.                         ulLap2 = m_apCars[m_aulPosition[usCount]]->m_ulLap;
  1098.  
  1099.                         if(m_apCars[m_aulPosition[usCmp]]->m_ulTrackNode == 0)
  1100.                             ulLap1++;
  1101.                         if(m_apCars[m_aulPosition[usCount]]->m_ulTrackNode == 0)
  1102.                             ulLap2++;
  1103.  
  1104.                         if(ulLap1 > ulLap2 || (ulLap1 == ulLap2 &&
  1105.                             m_apCars[m_aulPosition[usCmp]]->m_ulTrackNode > m_apCars[m_aulPosition[usCount]]->m_ulTrackNode) ||
  1106.                             m_apCars[m_aulPosition[usCount]]->m_State == DESTROYED)
  1107.                         {
  1108.                             ulTmp = m_aulPosition[usCmp];
  1109.                             m_aulPosition[usCmp] = m_aulPosition[usCount];
  1110.                             m_aulPosition[usCount] = ulTmp;
  1111.                         }
  1112.                         else if(ulLap1 == ulLap2 &&    m_apCars[m_aulPosition[usCmp]]->m_ulTrackNode == m_apCars[m_aulPosition[usCount]]->m_ulTrackNode)
  1113.                         {
  1114.                             Float fDist1, fDist2;
  1115.  
  1116.                             fDist1 = TEAbs(m_aTrackNodes[m_apCars[m_aulPosition[usCmp]]->m_ulTrackNode].m_Plane.DistanceToPlane(m_apCars[m_aulPosition[usCmp]]->m_Center));
  1117.                             fDist2 = TEAbs(m_aTrackNodes[m_apCars[m_aulPosition[usCount]]->m_ulTrackNode].m_Plane.DistanceToPlane(m_apCars[m_aulPosition[usCount]]->m_Center));
  1118.  
  1119.                             if(fDist1 < fDist2)
  1120.                             {
  1121.                                 ulTmp = m_aulPosition[usCmp];
  1122.                                 m_aulPosition[usCmp] = m_aulPosition[usCount];
  1123.                                 m_aulPosition[usCount] = ulTmp;
  1124.                             }
  1125.                         }
  1126.                     }
  1127.                 }
  1128.             }
  1129.         }
  1130.         
  1131.         for(usCount = 0; usCount < ulCars; usCount++)
  1132.         {
  1133.             if(m_apCars[usCount]->m_ulLap == m_ulNumLapsForCurrRace+1)
  1134.             {
  1135.                 if(m_aulPosition[0] == usCount)
  1136.                     m_apCars[usCount]->m_State = FINISHED1ST;
  1137.                 else if(m_aulPosition[1] == usCount)
  1138.                     m_apCars[usCount]->m_State = FINISHED2ND;
  1139.                 else if(m_aulPosition[2] == usCount)
  1140.                     m_apCars[usCount]->m_State = FINISHED3RD;
  1141.                 else if(m_aulPosition[3] == usCount)
  1142.                     m_apCars[usCount]->m_State = FINISHED4TH;
  1143.                 
  1144.                 m_apCars[usCount]->m_ulLap = m_ulNumLapsForCurrRace;
  1145.             }
  1146.  
  1147.             if(m_CurrGameType == KNOCKOUT || m_CurrGameType == POWERUPKO)
  1148.             {
  1149.                 if( (m_apCars[usCount]->m_ulLap == m_ulNumLapsForCurrRace-1 && m_aulPosition[3] == usCount) ||
  1150.                     (m_apCars[usCount]->m_ulLap == m_ulNumLapsForCurrRace && m_aulPosition[2] == usCount) ||
  1151.                     m_apCars[usCount]->m_State == FINISHED2ND)
  1152.                 {
  1153.                     if(m_apCars[usCount]->m_State == FINISHED2ND)
  1154.                         m_apCars[usCount]->m_ulLap = m_ulNumLapsForCurrRace+1;
  1155.  
  1156.                     m_apCars[usCount]->m_State = KO;
  1157.                 }
  1158.             }
  1159.  
  1160.             if(m_CurrGameType == RACETODEATH && m_apCars[usCount]->m_State == RACING &&
  1161.                 (m_apCars[usCount]->m_lPowerUpInfluence == POWERUP_MINE || m_apCars[usCount]->m_lPowerUpInfluence == POWERUP_ROCKET))
  1162.                 m_apCars[usCount]->m_State = DESTROYED;
  1163.         }
  1164.  
  1165.         if(m_CurrGameType == RACETODEATH)
  1166.         {
  1167.             usCmp = 0;
  1168.  
  1169.             for(usCount = 0; usCount < ulCars; usCount++)
  1170.             {
  1171.                 if(m_apCars[usCount]->m_State == DESTROYED)
  1172.                     usCmp++;
  1173.                 else
  1174.                     ulTmp = usCount;
  1175.             }
  1176.  
  1177.             if(usCmp == ulCars-1 && m_apCars[ulTmp]->m_State == RACING)
  1178.                 m_apCars[ulTmp]->m_State = FINISHED1ST;
  1179.         }
  1180.     }
  1181.  
  1182.     UInt32 ulSpeed = (UInt32) m_pCar->GetSpeedKMH();
  1183.     UInt32 ulDelta = TEAbs((Int32) m_ulTachoSpeed - (Int32) ulSpeed);
  1184.  
  1185.     if(ulDelta <= 3)
  1186.         m_ulTachoSpeed = ulSpeed;
  1187.     else
  1188.     {
  1189.         if(ulSpeed > m_ulTachoSpeed)
  1190.             m_ulTachoSpeed += 3;
  1191.         else if(ulSpeed < m_ulTachoSpeed)
  1192.             m_ulTachoSpeed -= 3 * (ulDelta / 10);
  1193.     }
  1194.  
  1195.     if(ulSpeed <= 3)
  1196.         m_ulTachoSpeed = 0;
  1197.  
  1198.     if(m_GameState == SERVERRACE)
  1199.     {
  1200.         FRCarUpdate Update;
  1201.         UInt32 aulPos[5];
  1202.  
  1203.         Update.ulMsgType = FRCARUPDATE;
  1204.  
  1205.         for(usCount = 0; usCount < m_ulNumClients+1; usCount++)
  1206.         {
  1207.             Update.ucCar = (UChar) usCount;
  1208.             Update.fGasPedal = m_apCars[usCount]->m_fPedal;
  1209.             Update.fSteeringWheel = m_apCars[usCount]->m_fSteeringWheel;
  1210.             Update.bHandbrake = m_apCars[usCount]->m_bHandbrake;
  1211.             Update.lGear = m_apCars[usCount]->m_lCurrentGear;
  1212.             Update.lPowerUp = m_apCars[usCount]->m_lPowerUp;
  1213.             Update.Pos = m_apCars[usCount]->m_Center;
  1214.             Update.Rotation = m_apCars[usCount]->m_Rotation;
  1215.             Update.Velocity = m_apCars[usCount]->m_Velocity;
  1216.             Update.State = m_apCars[usCount]->m_State;
  1217.             Update.ulLap = m_apCars[usCount]->m_ulLap;
  1218.  
  1219.             m_pNetworkManager->SendDataToAllClients(&Update, sizeof(Update));
  1220.         }
  1221.  
  1222.         aulPos[0] = FRPLACES;
  1223.         aulPos[1] = m_aulPosition[0];
  1224.         aulPos[2] = m_aulPosition[1];
  1225.         aulPos[3] = m_aulPosition[2];
  1226.         aulPos[4] = m_aulPosition[3];
  1227.         m_pNetworkManager->SendDataToAllClients(aulPos, sizeof(UInt32)*5);
  1228.     }
  1229. }
  1230.  
  1231. void FRApp::RenderRace(void)
  1232. {
  1233.     Char acInfo[128];
  1234.     UInt16 usCount;
  1235.     TEString Text;
  1236.  
  1237.     m_pRenderer->EnableBlending();
  1238.     m_pRenderer->SetBlendingState(BLEND_SRC_ALPHA, BLEND_ONE_MINUS_SRC_ALPHA);
  1239.  
  1240.     if(m_ulCountdown != 0)
  1241.     {
  1242.         UInt32 ulTime = m_pTimer->GetElapsedTime(m_ulCountdown);
  1243.         UChar ucState = 0;
  1244.  
  1245.         if(m_GameState != CLIENTRACE)
  1246.         {
  1247.             UInt32 ulTime = m_pTimer->GetElapsedTime(m_ulCountdown);
  1248.             
  1249.             if(ulTime <= 1000)
  1250.                 ucState = 1;
  1251.             else if(ulTime <= 2000)
  1252.                 ucState = 2;
  1253.             else if(ulTime <= 3000)
  1254.                 ucState = 3;
  1255.             else if(ulTime <= 3500)
  1256.                 ucState = 4;
  1257.             else if(m_GameState == SERVERRACE && ulTime <= 4000)
  1258.                 ucState = 0;
  1259.             else m_ulCountdown = 0;
  1260.  
  1261.             if(m_GameState == SERVERRACE)
  1262.             {
  1263.                 FRCountdown Msg;
  1264.                 Msg.ulMsgType = FRCOUNTDOWN;
  1265.                 Msg.ucState = ucState;
  1266.                 m_pNetworkManager->SendDataToAllClients(&Msg, sizeof(Msg));
  1267.             }
  1268.         }
  1269.         else ucState = (UChar) m_ulCountdown;
  1270.  
  1271.  
  1272.         if(ucState == 1)
  1273.         {
  1274.             m_pRenderer->SetAmbient(100, 0, 0, 250);
  1275.             sprintf(acInfo,"3");
  1276.             m_pRenderer->DrawText(m_usScreenWidth/2-14, m_usScreenHeight/2-16, 32, acInfo);
  1277.         }
  1278.         else if(ucState == 2)
  1279.         {
  1280.             m_pRenderer->SetAmbient(200, 0, 0, 250);
  1281.             sprintf(acInfo,"2");
  1282.             m_pRenderer->DrawText(m_usScreenWidth/2-14, m_usScreenHeight/2-16, 32, acInfo);
  1283.         }
  1284.         else if(ucState == 3)
  1285.         {
  1286.             m_pRenderer->SetAmbient(220, 220, 0, 250);
  1287.             sprintf(acInfo,"1");
  1288.             m_pRenderer->DrawText(m_usScreenWidth/2-14, m_usScreenHeight/2-16, 32, acInfo);
  1289.         }
  1290.         else if(ucState == 4)
  1291.         {
  1292.             ulTime = m_pTimer->GetTime();
  1293.  
  1294.             for(UInt16 usCount = 0; usCount < 4; usCount++)
  1295.             {
  1296.                 if(m_apCars[usCount] == NULL)
  1297.                     break;
  1298.  
  1299.                 m_apCars[usCount]->m_State = RACING;
  1300.                 m_apCars[usCount]->m_ulLastAINodeChange = ulTime;
  1301.             }
  1302.             
  1303.             m_pRenderer->SetAmbient(0, 150, 0, 250);
  1304.             sprintf(acInfo,"START!");
  1305.             m_pRenderer->DrawText(m_usScreenWidth/2-81, m_usScreenHeight/2-16, 32, acInfo);
  1306.         }
  1307.     }
  1308.     else if(m_pCar->m_State >= FINISHED1ST && m_pCar->m_State <= FINISHED4TH)
  1309.     {
  1310.         m_pRenderer->SetAmbient(200, 0, 0, 250);
  1311.  
  1312.         if(m_pCar->m_State == FINISHED1ST) Text = TETranslator::GetTranslator()->Translate("YOU WIN!");
  1313.         else if(m_pCar->m_State == FINISHED2ND) Text = TETranslator::GetTranslator()->Translate("Second Place");
  1314.         else if(m_pCar->m_State == FINISHED3RD) Text = TETranslator::GetTranslator()->Translate("Third Place");
  1315.         else if(m_pCar->m_State == FINISHED4TH) Text = TETranslator::GetTranslator()->Translate("Last Place");
  1316.  
  1317.         m_pRenderer->DrawText(m_usScreenWidth/2 - (UInt16) (Text.GetLength() * 13.6f), m_usScreenHeight/2-16, 32, Text);
  1318.     }
  1319.     else if(m_pCar->m_State == DESTROYED)
  1320.     {
  1321.         m_pRenderer->SetAmbient(200, 0, 0, 250);
  1322.  
  1323.         Text = TETranslator::GetTranslator()->Translate("CAR DESTROYED!");
  1324.         m_pRenderer->DrawText(m_usScreenWidth/2 - (UInt16) (Text.GetLength() * 13.6f), m_usScreenHeight/2-16, 32, Text);
  1325.     }
  1326.     else if(m_pCar->m_State == KO)
  1327.     {
  1328.         m_pRenderer->SetAmbient(200, 0, 0, 250);
  1329.  
  1330.         Text = "K.O.";
  1331.         m_pRenderer->DrawText(m_usScreenWidth/2 - (UInt16) (Text.GetLength() * 13.6f), m_usScreenHeight/2-16, 32, Text);
  1332.     }
  1333.     else
  1334.     {
  1335.         m_pRenderer->SetAmbient(0, 0, 255, 250);
  1336.  
  1337.         if(m_pCar->m_ulLap == 0)
  1338.             sprintf(acInfo, "1/%d", m_ulNumLapsForCurrRace);
  1339.         else sprintf(acInfo, "%d/%d", m_pCar->m_ulLap, m_ulNumLapsForCurrRace);
  1340.         Text = TETranslator::GetTranslator()->Translate("Lap:");
  1341.         Text = Text + acInfo;
  1342.         m_pRenderer->DrawText(0, 0, 16, Text);
  1343.     }
  1344.  
  1345.     if(m_bShowAbortMenu)
  1346.     {
  1347.         if(m_GameState == SERVERRACE)
  1348.             RenderInGameMenuServer();
  1349.         else if(m_GameState == CLIENTRACE)
  1350.             RenderInGameMenuClient();
  1351.         else
  1352.         {
  1353.             m_pRenderer->SetAmbient(0, 0, 200, 250);
  1354.  
  1355.             Text = TETranslator::GetTranslator()->Translate("Press ESCAPE to continue race.");
  1356.             m_pRenderer->DrawText(m_usScreenWidth/2 - (UInt16) (Text.GetLength() * 6.8f), m_usScreenHeight/2-16, 16, Text);
  1357.  
  1358.             Text = TETranslator::GetTranslator()->Translate("Press ENTER to go to main menu.");
  1359.             m_pRenderer->DrawText(m_usScreenWidth/2 - (UInt16) (Text.GetLength() * 6.8f), m_usScreenHeight/2, 16, Text);
  1360.         }
  1361.     }
  1362.  
  1363.     if(m_pCar->m_State != RACING && m_pCar->m_State != WAITING && m_GameState == RACE)
  1364.     {
  1365.         m_pRenderer->SetAmbient(0, 0, 200, 250);
  1366.  
  1367.         if(!m_bCareerRace)
  1368.             Text = TETranslator::GetTranslator()->Translate("Press ESCAPE to go to main menu");
  1369.         else Text = TETranslator::GetTranslator()->Translate("Press ESCAPE to continue");
  1370.         m_pRenderer->DrawText(m_usScreenWidth/2 - (UInt16) (Text.GetLength() * 6.8f), 0, 16, Text);
  1371.     }
  1372.  
  1373.     m_pRenderer->SetAmbient(0, 0, 255, 250);
  1374.  
  1375. #if TE_IS_DEBUG_VERSION == 1
  1376.     sprintf(acInfo, "FPS: %d", m_pRenderer->GetFPS());
  1377.     m_pRenderer->DrawText(0, m_usScreenHeight - 24, 16, acInfo);
  1378. #endif
  1379.  
  1380.     for(usCount = 0; usCount < 4; usCount++)
  1381.     {
  1382.         if(m_apCars[m_aulPosition[usCount]] == NULL ||
  1383.             m_apCars[m_aulPosition[usCount]]->m_State == KO || 
  1384.             m_apCars[m_aulPosition[usCount]]->m_State == WAITING)
  1385.             continue;
  1386.  
  1387.         if(usCount == 0) Text = "1: ";
  1388.         else if(usCount == 1) Text = "2: ";
  1389.         else if(usCount == 2) Text = "3: ";
  1390.         else if(usCount == 3) Text = "4: ";
  1391.  
  1392.         Text = Text + m_apCars[m_aulPosition[usCount]]->m_DriverName;
  1393.         m_pRenderer->DrawText(0, 25 + 20 * usCount, 16, Text);
  1394.     }
  1395.  
  1396.     m_pRenderer->DisableBlending();
  1397.  
  1398.     if(m_bShowTacho)
  1399.         RenderTacho();
  1400.     
  1401.     RenderPowerUpIcon(m_pCar->m_lPowerUp);
  1402.  
  1403.     if(m_bUseMirror)
  1404.         RenderMirror();
  1405. }
  1406.  
  1407. void FRApp::DoAI(FRCar* pCar)
  1408. {
  1409.     TEMatrix3x3 MatRot;
  1410.     TEVector Center = pCar->GetCenter();
  1411.     TEVector Rot = pCar->GetRotation();
  1412.     MatRot.YRotationMatrixDeg(-Rot.m_fY);
  1413.     TEVector Forward = pCar->GetVelocity();
  1414.     TEVector Diff = Center - m_aAINodes[pCar->m_ulAINode].m_Position;
  1415.     Float fSpeed, fD;
  1416.     UInt32 ulTmp, ulTime = TETimer::GetTimer()->GetTime();;
  1417.  
  1418.     fSpeed = pCar->GetSpeedKMH();
  1419.     
  1420.     pCar->SetHandbrake(false);
  1421.     pCar->SetPedal(1.0f);
  1422.  
  1423.     if(fSpeed > (m_aAINodes[pCar->m_ulAINode].m_fMaxSpeed * pCar->m_fAIEfficiency) + 40)
  1424.     {
  1425.         if(m_aAINodes[pCar->m_ulAINode].m_bHandbrake && fSpeed > 100)
  1426.             pCar->SetHandbrake(true);
  1427.         else pCar->SetPedal(-1.0f);
  1428.     }
  1429. //    else if(fSpeed >= (m_aAINodes[pCar->m_ulAINode].m_fMaxSpeed * pCar->m_fAIEfficiency))
  1430. //        pCar->SetPedal(0.9f);
  1431. //    else pCar->SetPedal(1.0f);
  1432.  
  1433.     Diff.m_fY = Forward.m_fY = 0;
  1434.     fD = Diff.GetLength();
  1435.  
  1436.     Diff = Diff * MatRot;
  1437.     Forward = Forward * MatRot;
  1438.     Diff.Normalize();
  1439.     Forward.Normalize();
  1440.  
  1441.     if(fD < 150.0f)
  1442.     {
  1443.         pCar->m_ulAINode++;
  1444.  
  1445.         if(pCar->m_ulAINode >= m_ulNumAINodes)
  1446.             pCar->m_ulAINode = 0;
  1447.  
  1448.         pCar->m_ulLastAINodeChange = ulTime;
  1449.     }
  1450.  
  1451. //    if(m_aAINodes[pCar->m_ulAINode].m_bHandbrake && fSpeed > 100)
  1452. //        pCar->SetHandbrake(true);
  1453. //    else pCar->SetHandbrake(false);
  1454.  
  1455.     if(pCar->m_lPowerUpInfluence == POWERUP_OIL)
  1456.     {
  1457.         if(fSpeed > 20.0f)
  1458.         {
  1459.             if(pCar->m_ulPowerUpEndTime - m_pTimer->GetTime() < 700)
  1460.             {
  1461.                 pCar->SetHandbrake(true);
  1462.  
  1463.                 if(pCar->m_lCurrentGear != REVERSE_GEAR)
  1464.                     pCar->SetPedal(-1.0f);
  1465.                 else pCar->SetPedal(1.0f);
  1466.             }
  1467.             else pCar->SetPedal(0.0f);
  1468.         }
  1469.         else
  1470.         {
  1471.             pCar->SetHandbrake(false);
  1472.             pCar->SetPedal(0.5f);
  1473.         }
  1474.     }
  1475.  
  1476.     if(fSpeed > 0)
  1477.     {
  1478.         if(Diff.m_fX > 0.15f)
  1479.         {
  1480.             pCar->SetSteeringWheel(-1.0f);
  1481.         }
  1482.         else if(Diff.m_fX < -0.15f)
  1483.         {
  1484.             pCar->SetSteeringWheel(1.0f);
  1485.         }
  1486.         else pCar->SetSteeringWheel(0.0f);
  1487.     }
  1488.     else pCar->SetSteeringWheel(0.0f);
  1489.  
  1490.     if(pCar->m_lPowerUp != -1)
  1491.     {
  1492.         if(pCar->m_lPowerUp == POWERUP_N2O)
  1493.             pCar->EnablePowerUp();
  1494.         else if(pCar->m_lPowerUp == POWERUP_ROCKET)
  1495.         {
  1496.             TEVector Dir = pCar->m_Forward * 750.0f * pCar->m_fAIEfficiency;
  1497.             TEClipInfo Info;
  1498.  
  1499.             if(m_pEngine->RayClipsInWorld(pCar->m_Center, Dir, Info, pCar) &&
  1500.                 TEIsDerivedFromClass(FRCar, Info.pObject))
  1501.                 pCar->EnablePowerUp();
  1502.  
  1503.         }
  1504.         else
  1505.         {
  1506.             TEVector Dir = pCar->m_Forward * (-250.0f - 75.0f * pCar->m_fAIEfficiency);
  1507.             TEClipInfo Info;
  1508.  
  1509.             if(m_pEngine->RayClipsInWorld(pCar->m_Center, Dir, Info, pCar) &&
  1510.                 TEIsDerivedFromClass(FRCar, Info.pObject))
  1511.                 pCar->EnablePowerUp();
  1512.  
  1513.         }
  1514.     }
  1515.  
  1516.     if(ulTime - pCar->m_ulLastAINodeChange > 20000 && pCar->m_State == RACING)
  1517.     {
  1518.         ulTmp = pCar->m_ulAINode;
  1519.         
  1520.         pCar->m_ulLastAINodeChange = ulTime;
  1521.  
  1522.         if(ulTmp == 0)
  1523.             ulTmp = m_ulNumTrackNodes-1;
  1524.         else ulTmp--;
  1525.  
  1526.         Forward = m_aAINodes[ulTmp].m_Position - m_aAINodes[pCar->m_ulAINode].m_Position;
  1527.         Forward.Normalize();
  1528.  
  1529.         pCar->Reset(m_aAINodes[ulTmp].m_Position, Forward);
  1530.     }
  1531. }
  1532.  
  1533. FRCar* FRApp::GetAICar(TEVector &rCenter, Float fInitYRot, Int32 &rlAI1, Int32 &rlAI2)
  1534. {
  1535.     Int32 lDriver = TERandM(25)-1;
  1536.     FRCar* pCar;
  1537.  
  1538.     while(rlAI1 == lDriver || rlAI2 == lDriver)
  1539.         lDriver = TERandM(25)-1;
  1540.  
  1541.     if(rlAI1 == -1)
  1542.         rlAI1 = lDriver;
  1543.     else if(rlAI2 == -1)
  1544.         rlAI2 = lDriver;
  1545.  
  1546.     pCar = GetCar(ms_aOpponents[lDriver].m_Car, rCenter, fInitYRot);
  1547.  
  1548.     pCar->m_DriverName = ms_aOpponents[lDriver].m_Name;
  1549.     pCar->m_bAIUsesHorn = ms_aOpponents[lDriver].m_bUsesHorn;
  1550.     pCar->m_fAIEfficiency = ms_aOpponents[lDriver].m_fAIEfficiency;
  1551.  
  1552.     if(pCar->m_fRotFactor < 120.0f)
  1553.         pCar->m_fRotFactor = 120.0f;
  1554.  
  1555.     return pCar;
  1556. }
  1557.  
  1558. void FRApp::RenderTacho()
  1559. {
  1560.     Float fAngle, fX, fY;
  1561.  
  1562.     if(m_ulTachoSpeed > 200)
  1563.         m_ulTachoSpeed = 200;
  1564.  
  1565.     fAngle = m_ulTachoSpeed * 0.9f;    // 0░ = 0 km/h  180░ = 200 km/h
  1566.     fY = TESinDeg(fAngle) * 0.08f;
  1567.     fX = TECosDeg(fAngle) * 0.08f;
  1568.  
  1569.     m_pRenderer->SetTexture(m_pTacho);
  1570.     m_pRenderer->EnableBlending();
  1571.     m_pRenderer->SetBlendingState(BLEND_SRC_ALPHA, BLEND_ONE_MINUS_SRC_ALPHA);
  1572.     m_pRenderer->SetAmbient(255, 255, 255, 255);
  1573.     m_pRenderer->DrawRectanglef(0.8f, 0.875f, 0.98f, 0.975f);
  1574.     m_pRenderer->DisableBlending();
  1575.  
  1576.  
  1577.     m_pRenderer->SetTexture(NULL);
  1578.     m_pRenderer->SetAmbient(255, 0, 0);
  1579.     m_pRenderer->DrawLinef(0.89f-fX, 0.97f-fY, 0.89f, 0.97f, 2.0f);
  1580. }
  1581.  
  1582. void FRApp::RenderPowerUpIcon(Int32 lPowerUp)
  1583. {
  1584.     if(lPowerUp > 3 || lPowerUp < 0)
  1585.         return;
  1586.  
  1587.     m_pRenderer->EnableBlending();
  1588.     m_pRenderer->SetTexture(m_apPowerUpIcons[lPowerUp]);
  1589.     m_pRenderer->SetBlendingState(BLEND_SRC_ALPHA, BLEND_ONE_MINUS_SRC_ALPHA);
  1590.     m_pRenderer->SetAmbient(255, 255, 255, 255);
  1591.     m_pRenderer->DrawRectangle(m_usScreenWidth-64, 0, m_usScreenWidth, 64);
  1592.     m_pRenderer->SetAmbient(0, 0, 200, 250);
  1593.     m_pRenderer->DrawText(m_usScreenWidth-154, 20, 16, "POWERUP");
  1594.  
  1595.     // hardcoded translation to improve performance
  1596.     if(m_Lang == GERMAN)
  1597.         m_pRenderer->DrawText(m_usScreenWidth-158, 36, 14, "VERF▄GBAR");
  1598.     else m_pRenderer->DrawText(m_usScreenWidth-158, 36, 14, "AVAILABLE");
  1599.  
  1600.     m_pRenderer->DisableBlending();
  1601.  
  1602. }
  1603.  
  1604. void FRApp::RenderMirror(void)
  1605. {
  1606.     TECamera* pCam = m_pRenderer->GetCamera();
  1607.     TECamera Tmp = *pCam;
  1608.     TEVector* pPos = pCam->GetPositionPointer();
  1609.     TEVector* pRot = pCam->GetRotationPointer();
  1610.     UInt16 usX = (UInt16) ((m_usScreenWidth - m_usMirrorWidth) * 0.5f);
  1611.     UInt16 usY = MIRROR_POS;
  1612.     FRCarVisibility Vis;
  1613.     bool bDecals = m_pEngine->GetDecalUse();
  1614.     bool bDynLights = m_pEngine->GetDynamicLightUse();
  1615.     bool bRefl = m_pEngine->GetReflectionUse();
  1616.     TEShadowMethod Shadow = m_pEngine->GetShadowMethod();
  1617.  
  1618.     m_pRenderer->SetTexture(NULL);
  1619.     m_pRenderer->SetAmbient(0, 0, 0);
  1620.     m_pRenderer->DrawRectangle(usX - 5, usY - 5, usX + m_usMirrorWidth + 5, usY + m_usMirrorHeight + 5);
  1621.  
  1622.     *pPos = m_pCar->m_pBoundingVolume->GetCenter() - m_pCar->m_Forward * m_pCar->m_CarSize.m_fZ * 0.5f;
  1623.     pPos->m_fY += m_pCar->m_CarSize.m_fY * 0.25f;
  1624.     pRot->m_fX = pRot->m_fZ = 0.0f;
  1625.     pRot->m_fY = 180.0f - m_pCar->m_Rotation.m_fY;
  1626.  
  1627.     pCam->SetPerspective(30.0f, (Float) m_usMirrorWidth / (Float) m_usMirrorHeight, Tmp.GetZNear(), Tmp.GetZFar());
  1628.     pCam->UpdateCamera();
  1629.  
  1630.     Vis = m_pCar->m_Visibility;
  1631.     m_pCar->m_Visibility = INVISIBLE;
  1632.  
  1633.     m_pEngine->SetDecalUse(false);
  1634.     m_pEngine->SetDynamicLightUse(false);
  1635.     m_pEngine->SetReflectionUse(false);
  1636.     m_pEngine->SetShadowMethod(SHADOW_NONE);
  1637.  
  1638.     m_pRenderer->SetViewport(usX, usY, m_usMirrorWidth, m_usMirrorHeight);
  1639.     m_pRenderer->ClearZBuffer();
  1640.     m_pRenderer->ResetWorld();
  1641.     m_pRenderer->ScaleWorld(-1.0f, 1.0f, 1.0f);
  1642.     m_pRenderer->ReverseVertexOrder(true);
  1643.     m_pRenderer->RotateWorldDeg(pRot->m_fX, pRot->m_fY, pRot->m_fZ);
  1644.     m_pRenderer->TransformWorld(-pPos->m_fX, -pPos->m_fY, -pPos->m_fZ);
  1645.     RenderWorld();
  1646.  
  1647.     m_pCar->m_Visibility = Vis;
  1648.  
  1649.     *pCam = Tmp;
  1650.     m_pRenderer->SetViewport(0, 0, m_usScreenWidth, m_usScreenHeight);
  1651.     m_pRenderer->ReverseVertexOrder(false);
  1652.  
  1653.     m_pEngine->SetDecalUse(bDecals);
  1654.     m_pEngine->SetDynamicLightUse(bDynLights);
  1655.     m_pEngine->SetReflectionUse(bRefl);
  1656.     m_pEngine->SetShadowMethod(Shadow);
  1657. }
  1658.  
  1659. void FRApp::LoadRes(void)
  1660. {
  1661.     TETextureManager* pTex = TETextureManager::GetTextureManager();
  1662.     TEString Name, Pak;
  1663.     UChar aucColorkey[] = {0, 0, 255};
  1664.     UInt32 ulCount;
  1665.  
  1666.     Pak = "HUD";
  1667.     Name = "tacho";
  1668.     m_pTacho = pTex->GetTexture(Name, Pak, false, aucColorkey);
  1669.     Name = "N2O";
  1670.     m_apPowerUpIcons[0] = pTex->GetTexture(Name, Pak, false, aucColorkey);
  1671.     Name = "rocket";
  1672.     m_apPowerUpIcons[1] = pTex->GetTexture(Name, Pak, false, aucColorkey);
  1673.     Name = "mine";
  1674.     m_apPowerUpIcons[2] = pTex->GetTexture(Name, Pak, false, aucColorkey);
  1675.     Name = "oil";
  1676.     m_apPowerUpIcons[3] = pTex->GetTexture(Name, Pak, false, aucColorkey);
  1677.  
  1678.     Pak = "menu";
  1679.     Name = "background";
  1680.  
  1681.     m_pMenuBackground = pTex->GetTexture(Name, Pak, false);
  1682.  
  1683.     Pak = "tracks";
  1684.  
  1685.     for(ulCount = 0; ulCount < NUM_TRACKS; ulCount++)
  1686.     {
  1687.         Name = ms_aacTrackNames[ulCount];
  1688.         m_apTrackImages[ulCount] = pTex->GetTexture(Name, Pak, false);
  1689.     }
  1690. }
  1691.  
  1692. void FRApp::LoadCurrTrack(void)
  1693. {
  1694.     TEString Tmp = TETranslator::GetTranslator()->Translate("Loading...");
  1695.     
  1696.     m_pRenderer->SetAmbient(255,255,255,255);
  1697.     m_pRenderer->SetTexture(m_pMenuBackground);
  1698.     m_pRenderer->DrawRectanglef(0.0f, 0.0f, 1.0f, 1.0f);
  1699.     m_pRenderer->SetAmbient(0,0,200,255);
  1700.     m_pRenderer->DrawText(m_usScreenWidth / 2 - (UInt32) (Tmp.GetLength() * 6.8f), m_usScreenHeight / 2 - 8, 16, Tmp);
  1701.     m_pRenderer->DisplayBackBuffer();
  1702.  
  1703.     m_ulNumTrackNodes = 0;
  1704.     m_aTempTrackNodes = new FRTrackNode[MAX_NODES];
  1705.  
  1706.     m_ulNumAINodes = 0;
  1707.     m_aTempAINodes = new FRAINode[MAX_NODES];
  1708.  
  1709.     if(m_CurrGameType == NORMALRACE || m_CurrGameType == KNOCKOUT)
  1710.             FRCar::ms_bPowerUpsEnabled = false;
  1711.     else FRCar::ms_bPowerUpsEnabled = true;
  1712.  
  1713.     Tmp = ms_aacTrackNames[m_ulCurrTrack];
  1714.     Tmp = Tmp + ".bsp";
  1715.     UnloadBSPFile();
  1716.  
  1717.     LoadBSPFile(Tmp);
  1718.  
  1719.     SafeDeleteA(m_aTrackNodes);
  1720.     SafeDeleteA(m_aAINodes);
  1721.  
  1722.     m_aTrackNodes =  new FRTrackNode[m_ulNumTrackNodes];
  1723.     m_aAINodes = new FRAINode[m_ulNumAINodes];
  1724.  
  1725.     memcpy(m_aTrackNodes, m_aTempTrackNodes, sizeof(FRTrackNode)*m_ulNumTrackNodes);
  1726.     memcpy(m_aAINodes, m_aTempAINodes, sizeof(FRAINode)*m_ulNumAINodes);
  1727.  
  1728.     SafeDeleteA(m_aTempTrackNodes);
  1729.     SafeDeleteA(m_aTempAINodes);
  1730.  
  1731.     if(m_Details == LOW || m_Details == VERYLOW)
  1732.     {
  1733.         TEEngineObject *pTmp, *pBuf;
  1734.  
  1735.         pTmp = m_pEngine->GetObjectsInWorld();
  1736.         pBuf = NULL;
  1737.  
  1738.         while(pTmp != NULL)
  1739.         {
  1740.             // remove TEModelObjects to improve performance
  1741.             if(TEIsTypeOfClass(TEModelObject, pTmp))
  1742.                 pBuf = pTmp;
  1743.  
  1744.             pTmp = pTmp->m_pNext;
  1745.  
  1746.             SafeDelete(pBuf);
  1747.         }
  1748.  
  1749.         // No ParticleFX to improve performance
  1750.         m_pEngine->FreeAllParticleSystems();
  1751.     }
  1752. }
  1753.  
  1754. void FRApp::StartRace(void)
  1755. {
  1756.     Int32 lNumTracks, lAI1, lAI2;
  1757.     Char acTmp[32];
  1758.     TEString Name;
  1759.  
  1760.     if(m_pBackgroundMusic != NULL)
  1761.     {
  1762.         m_pBackgroundMusic->Stop();
  1763.         SafeDelete(m_pBackgroundMusic);
  1764.     }
  1765.  
  1766.     switch(m_Music){
  1767.     case DEFAULT:
  1768.         sprintf(acTmp, "music%d.ogg", TERandM(4));
  1769.         Name = acTmp;
  1770.         m_pBackgroundMusic = TESoundManager::GetSoundManager()->GetSound(Name);
  1771.         m_pBackgroundMusic->Play(TESOUND_LOOP, m_fGeneralVolume * m_fMusicVolume);
  1772.         break;
  1773.     case FROMCD:
  1774.         lNumTracks = m_pCDPlayer->GetNumberOfTracks();
  1775.         
  1776.         if(lNumTracks > 0)
  1777.             m_pCDPlayer->Play(TERandM(lNumTracks)-1);
  1778.         break;
  1779.     };
  1780.  
  1781.     lAI1 = lAI2 = -1;
  1782.  
  1783.     m_apCars[0] = GetAICar(m_aStartPositions[0], m_aStartRotations[0], lAI1, lAI2);
  1784.     m_pEngine->AddObjectToWorld(m_apCars[0]);
  1785.  
  1786.     m_apCars[1] = GetAICar(m_aStartPositions[1], m_aStartRotations[1], lAI1, lAI2);
  1787.     m_pEngine->AddObjectToWorld(m_apCars[1]);
  1788.  
  1789.     m_apCars[2] = GetAICar(m_aStartPositions[2], m_aStartRotations[2], lAI1, lAI2);
  1790.     m_pEngine->AddObjectToWorld(m_apCars[2]);
  1791.  
  1792.     m_apCars[3] = m_pCar = GetCar(m_CurrCar, m_aStartPositions[3], m_aStartRotations[3]);
  1793.     m_pCar->m_Type = LOCAL;
  1794.     m_pCar->m_DriverName = m_PlayerName;
  1795.     m_pEngine->AddObjectToWorld(m_pCar);
  1796.     
  1797.     TETextureManager::GetTextureManager()->ReleaseUnusedTextures();
  1798.     TEModelManager::GetModelManager()->FreeUnusedModels();
  1799.     TESoundManager::GetSoundManager()->FreeUnusedSounds();
  1800.  
  1801.     m_aulPosition[0] = 0;
  1802.     m_aulPosition[1] = 1;
  1803.     m_aulPosition[2] = 2;
  1804.     m_aulPosition[3] = 3;
  1805.  
  1806.     m_fCamDelta = 0;
  1807.     m_ulTachoSpeed = 0;
  1808.     m_pEngine->ShowCursor(false);
  1809.     m_ulCountdown = m_pTimer->GetTime();
  1810.     m_bShowAbortMenu = false;
  1811. }
  1812.  
  1813. void FRApp::ExitRace(void)
  1814. {
  1815.     UnloadBSPFile();
  1816.     m_pEngine->ShowCursor(true);
  1817.     m_bShowAbortMenu = false;
  1818.     
  1819.     if(m_pBackgroundMusic != NULL && m_pBackgroundMusic->IsPlaying())
  1820.     {
  1821.         m_pBackgroundMusic->Stop();
  1822.         SafeDelete(m_pBackgroundMusic);
  1823.     }
  1824.     else if(m_Music == FROMCD)
  1825.         m_pCDPlayer->Stop();
  1826.  
  1827.     if(m_GameState == SERVERRACE)
  1828.         m_pNetworkManager->EndServer();
  1829.     else if(m_GameState == CLIENTRACE)
  1830.         m_pNetworkManager->EndClient();
  1831.  
  1832.     m_GameState = MAINMENU;
  1833. }
  1834.  
  1835. void FRApp::LoadConfig(void)
  1836. {
  1837.     FILE* pFile = fopen("frconfig.dat", "rb");
  1838.     TETranslator *pTrans = TETranslator::GetTranslator();
  1839.     TEString Language;
  1840.     TEString LangFile = "strings.txt";
  1841.     UInt32 ulSize;
  1842.     Char* acName;
  1843.  
  1844.     if(pFile == NULL)
  1845.     {
  1846.         m_usScreenWidth = 640;
  1847.         m_usScreenHeight = 480;
  1848.         m_usScreenBpp = 16;
  1849.         m_bPlayIntro = true;
  1850.         m_bShowTacho = false;
  1851.         m_bCamAnimation = true;
  1852.         m_bUseMirror = true;
  1853.         m_Lang = ENGLISH;
  1854.         m_Details = MEDIUM;
  1855.         m_Music = DEFAULT;
  1856.         m_fGeneralVolume =    0.8f;
  1857.         m_fMusicVolume = 2.5f;
  1858.         m_bUseJoystick = false;
  1859.         m_JoystickAccel = YAXIS;
  1860.         m_fJoystickSensitivity = 1.0f;
  1861.         m_bBonusCarAvailable = false;
  1862.         m_ulCurrCamPos = 1;
  1863.         m_ulCurrTrack = 0;
  1864.         m_ulNumLaps = 4;
  1865.         m_CurrGameType = NORMALRACE;
  1866.         m_CurrCar = HUMMER;
  1867.         m_PlayerName = "Trainee";
  1868.         m_usNetPort = 2000;
  1869.         m_IP.aucAddress[0] = 192;
  1870.         m_IP.aucAddress[1] = 168;
  1871.         m_IP.aucAddress[2] =   0;
  1872.         m_IP.aucAddress[3] =   1;
  1873.  
  1874.         m_aulKeys[GAS] = TE_KEY_UP;
  1875.         m_aulKeys[BRAKE] = TE_KEY_DOWN;
  1876.         m_aulKeys[LEFT] = TE_KEY_LEFT;
  1877.         m_aulKeys[RIGHT] = TE_KEY_RIGHT;
  1878.         m_aulKeys[HANDBRAKE] = TE_KEY_SPACE;
  1879.         m_aulKeys[HORN] = TE_KEY_ENTER;
  1880.         m_aulKeys[POWERUP] = TE_KEY_CTRL;
  1881.         m_aulKeys[RESET] = TE_KEY_R;
  1882.         m_aulKeys[CAMPOS] = TE_KEY_C;
  1883.         m_aulKeys[LOOKBACK] = TE_KEY_BACKSPACE;
  1884.         m_aulKeys[SCREENSHOT] = TE_KEY_F12;
  1885.     }
  1886.     else
  1887.     {
  1888.         fread(&m_usScreenWidth, sizeof(UInt16), 1, pFile);
  1889.         fread(&m_usScreenHeight, sizeof(UInt16), 1, pFile);
  1890.         fread(&m_usScreenBpp, sizeof(UInt16), 1, pFile);
  1891.         fread(&m_bPlayIntro, sizeof(bool), 1, pFile);
  1892.         fread(&m_bShowTacho, sizeof(bool), 1, pFile);
  1893.         fread(&m_bCamAnimation, sizeof(bool), 1, pFile);
  1894.         fread(&m_bUseMirror, sizeof(bool), 1, pFile);
  1895.         fread(&m_Lang, sizeof(FRLanguage), 1, pFile);
  1896.         fread(&m_Details, sizeof(FRDetailLevel), 1, pFile);
  1897.         fread(&m_Music, sizeof(FRBackgroundMusic), 1, pFile);
  1898.         fread(&m_fGeneralVolume, sizeof(Float), 1, pFile);
  1899.         fread(&m_fMusicVolume, sizeof(Float), 1, pFile);
  1900.         fread(m_aulKeys, sizeof(TEKeyState), NUM_KEYS, pFile);
  1901.         fread(&m_bUseJoystick, sizeof(bool), 1, pFile);
  1902.         fread(&m_JoystickAccel, sizeof(FRJoystickAccel), 1, pFile);
  1903.         fread(&m_fJoystickSensitivity, sizeof(Float), 1, pFile);
  1904.         fread(&m_bBonusCarAvailable, sizeof(bool), 1, pFile);
  1905.         fread(&m_ulCurrCamPos, sizeof(UInt32), 1, pFile);
  1906.         fread(&m_ulCurrTrack, sizeof(UInt32), 1, pFile);
  1907.         fread(&m_ulNumLaps, sizeof(UInt32), 1, pFile);
  1908.         fread(&m_CurrGameType, sizeof(FRGameType), 1, pFile);
  1909.         fread(&m_CurrCar, sizeof(FRCarName), 1, pFile);
  1910.         fread(&ulSize, sizeof(UInt32), 1, pFile);
  1911.  
  1912.         acName = new Char[ulSize + 1];
  1913.         fread(acName, sizeof(Char), ulSize, pFile);
  1914.         acName[ulSize] = '\0';
  1915.         m_PlayerName.Set(acName);
  1916.         SafeDeleteA(acName);
  1917.  
  1918.         fread(&m_IP, sizeof(m_IP), 1, pFile);
  1919.         fread(&m_usNetPort, sizeof(UInt16), 1, pFile);
  1920.         
  1921.         fclose(pFile);
  1922.     }
  1923.  
  1924.     if(m_Lang == ENGLISH)
  1925.         Language = "ENGLISH";
  1926.     else if(m_Lang == GERMAN)
  1927.         Language = "GERMAN";
  1928.  
  1929.     pTrans->SetLanguage(Language, LangFile);
  1930.  
  1931.     pFile = fopen("frcareer.dat", "rb");
  1932.  
  1933.     if(pFile != NULL)
  1934.     {
  1935.         m_pCareer = new FRCareerInfo;
  1936.  
  1937.         fread(m_pCareer, sizeof(FRCareerInfo), 1, pFile);
  1938.         
  1939.         m_usDifficulty = m_pCareer->usDifficulty;
  1940.  
  1941.         fclose(pFile);
  1942.     }
  1943.     else m_pCareer = NULL;
  1944. }
  1945.  
  1946. void FRApp::SaveConfig(void)
  1947. {
  1948.     FILE* pFile = fopen("frconfig.dat", "wb");
  1949.     UInt32 ulSize = m_PlayerName.GetLength();
  1950.     Char *pcName = m_PlayerName.Get();
  1951.  
  1952.     if(pFile == NULL)
  1953.         return;
  1954.  
  1955.     fwrite(&m_usScreenWidth, sizeof(UInt16), 1, pFile);
  1956.     fwrite(&m_usScreenHeight, sizeof(UInt16), 1, pFile);
  1957.     fwrite(&m_usScreenBpp, sizeof(UInt16), 1, pFile);
  1958.     fwrite(&m_bPlayIntro, sizeof(bool), 1, pFile);
  1959.     fwrite(&m_bShowTacho, sizeof(bool), 1, pFile);
  1960.     fwrite(&m_bCamAnimation, sizeof(bool), 1, pFile);
  1961.     fwrite(&m_bUseMirror, sizeof(bool), 1, pFile);
  1962.     fwrite(&m_Lang, sizeof(FRLanguage), 1, pFile);
  1963.     fwrite(&m_Details, sizeof(FRDetailLevel), 1, pFile);
  1964.     fwrite(&m_Music, sizeof(FRBackgroundMusic), 1, pFile);
  1965.     fwrite(&m_fGeneralVolume, sizeof(Float), 1, pFile);
  1966.     fwrite(&m_fMusicVolume, sizeof(Float), 1, pFile);
  1967.     fwrite(m_aulKeys, sizeof(TEKeyState), NUM_KEYS, pFile);
  1968.     fwrite(&m_bUseJoystick, sizeof(bool), 1, pFile);
  1969.     fwrite(&m_JoystickAccel, sizeof(FRJoystickAccel), 1, pFile);
  1970.     fwrite(&m_fJoystickSensitivity, sizeof(Float), 1, pFile);
  1971.     fwrite(&m_bBonusCarAvailable, sizeof(bool), 1, pFile);
  1972.     fwrite(&m_ulCurrCamPos, sizeof(UInt32), 1, pFile);
  1973.     fwrite(&m_ulCurrTrack, sizeof(UInt32), 1, pFile);
  1974.     fwrite(&m_ulNumLaps, sizeof(UInt32), 1, pFile);
  1975.     fwrite(&m_CurrGameType, sizeof(FRGameType), 1, pFile);
  1976.     fwrite(&m_CurrCar, sizeof(FRCarName), 1, pFile);
  1977.     fwrite(&ulSize, sizeof(UInt32), 1, pFile);
  1978.     fwrite(pcName, sizeof(Char), ulSize, pFile);
  1979.     fwrite(&m_IP, sizeof(m_IP), 1, pFile);
  1980.     fwrite(&m_usNetPort, sizeof(UInt16), 1, pFile);
  1981.  
  1982.     fclose(pFile);
  1983. }
  1984.  
  1985. void FRApp::SaveCareer(void)
  1986. {
  1987.     TEAssert(m_pCareer);
  1988.  
  1989.     FILE* pFile = fopen("frcareer.dat", "wb");
  1990.  
  1991.     if(pFile == NULL)
  1992.         return;
  1993.  
  1994.     fwrite(m_pCareer, sizeof(FRCareerInfo), 1, pFile);
  1995.  
  1996.     fclose(pFile);
  1997. }
  1998.  
  1999. void FRApp::ApplyDetailSettings(void)
  2000. {
  2001.     switch(m_Details){
  2002.     case VERYHIGH:
  2003.         m_pRenderer->SetPerspective(90.0f, 4.0f/3.0f, 1.0f, 2500.0f);
  2004.         m_pEngine->SetShadowMethod(SHADOW_STENCIL_VOLUME);
  2005.         m_pEngine->SetModelDetail(LOD_FULL);
  2006.         m_pEngine->SetModelShadowLOD(SHADOWLOD_ONE_MINUS_CURRENT);
  2007.         m_pEngine->SetMaxDecalDistance(1000.0f);
  2008.         m_pEngine->SetMaxDecals(150);
  2009.         m_pEngine->SetMaxCoronaDistance(1250.0f);
  2010.         m_pEngine->SetMaxShadowDistance(1000.0f);
  2011.         m_pEngine->SetMaxDynamicLightDistance(1000.0f);
  2012.         m_pEngine->SetDecalUse(true);
  2013.         m_pEngine->SetLightMapping(true);
  2014.         m_pEngine->SetTextureDetail(TEXTURE_FULL);
  2015.         m_pEngine->SetDynamicLightUse(true);
  2016.         FRCar::ms_bTyreDecals = true;
  2017.         FRCar::ms_bSmoke = true;
  2018.         break;
  2019.     case HIGH:
  2020.         m_pRenderer->SetPerspective(90.0f, 4.0f/3.0f, 1.0f, 2250.0f);
  2021.         m_pEngine->SetShadowMethod(SHADOW_PROJECTED_STENCIL);
  2022.         m_pEngine->SetModelDetail(LOD_FULL);
  2023.         m_pEngine->SetModelShadowLOD(SHADOWLOD_ONE_MINUS_CURRENT);
  2024.         m_pEngine->SetMaxDecalDistance(750.0f);
  2025.         m_pEngine->SetMaxDecals(100);
  2026.         m_pEngine->SetMaxCoronaDistance(1000.0f);
  2027.         m_pEngine->SetMaxShadowDistance(750.0f);
  2028.         m_pEngine->SetMaxDynamicLightDistance(750.0f);
  2029.         m_pEngine->SetDecalUse(true);
  2030.         m_pEngine->SetLightMapping(true);
  2031.         m_pEngine->SetTextureDetail(TEXTURE_FULL);
  2032.         m_pEngine->SetDynamicLightUse(true);
  2033.         FRCar::ms_bTyreDecals = true;
  2034.         FRCar::ms_bSmoke = true;
  2035.         break;
  2036.     case MEDIUM:
  2037.         m_pRenderer->SetPerspective(90.0f, 4.0f/3.0f, 1.0f, 1750.0f);
  2038.         m_pEngine->SetShadowMethod(SHADOW_PROJECTED);
  2039.         m_pEngine->SetModelDetail(LOD_MEDIUM);
  2040.         m_pEngine->SetModelShadowLOD(SHADOWLOD_LAST);
  2041.         m_pEngine->SetMaxDecalDistance(600.0f);
  2042.         m_pEngine->SetMaxDecals(50);
  2043.         m_pEngine->SetMaxCoronaDistance(750.0f);
  2044.         m_pEngine->SetMaxShadowDistance(500.0f);
  2045.         m_pEngine->SetMaxDynamicLightDistance(500.0f);
  2046.         m_pEngine->SetDecalUse(true);
  2047.         m_pEngine->SetLightMapping(true);
  2048.         m_pEngine->SetTextureDetail(TEXTURE_FULL);
  2049.         m_pEngine->SetDynamicLightUse(true);
  2050.         FRCar::ms_bTyreDecals = true;
  2051.         FRCar::ms_bSmoke = false;
  2052.         break;
  2053.     case LOW:
  2054.         m_pRenderer->SetPerspective(90.0f, 4.0f/3.0f, 1.0f, 1500.0f);
  2055.         m_pEngine->SetShadowMethod(SHADOW_FAKE);
  2056.         m_pEngine->SetModelDetail(LOD_MEDIUM);
  2057.         m_pEngine->SetModelShadowLOD(SHADOWLOD_LAST);
  2058.         m_pEngine->SetMaxDecalDistance(512.0f);
  2059.         m_pEngine->SetMaxCoronaDistance(750.0f);
  2060.         m_pEngine->SetMaxShadowDistance(300.0f);
  2061.         m_pEngine->SetDecalUse(false);
  2062.         m_pEngine->SetLightMapping(false);
  2063.         m_pEngine->SetTextureDetail(TEXTURE_FULL);
  2064.         m_pEngine->SetDynamicLightUse(false);
  2065.         FRCar::ms_bTyreDecals = false;
  2066.         FRCar::ms_bSmoke = false;
  2067.         break;
  2068.     case VERYLOW:
  2069.         m_pRenderer->SetPerspective(90.0f, 4.0f/3.0f, 1.0f, 1250.0f);
  2070.         m_pEngine->SetShadowMethod(SHADOW_NONE);
  2071.         m_pEngine->SetModelDetail(LOD_LOWEST);
  2072.         m_pEngine->SetModelShadowLOD(SHADOWLOD_LAST);
  2073.         m_pEngine->SetMaxDecalDistance(512.0f);
  2074.         m_pEngine->SetMaxCoronaDistance(750.0f);
  2075.         m_pEngine->SetDecalUse(false);
  2076.         m_pEngine->SetLightMapping(false);
  2077.         m_pEngine->SetTextureDetail(TEXTURE_MEDIUM);
  2078.         m_pEngine->SetDynamicLightUse(false);
  2079.         FRCar::ms_bTyreDecals = false;
  2080.         FRCar::ms_bSmoke = false;
  2081.         break;
  2082.     };
  2083.  
  2084.  
  2085.     m_usMirrorWidth = (UInt16) (300.0f * m_usScreenWidth / 1024.0f);
  2086.     m_usMirrorHeight = m_usMirrorWidth / 4;
  2087. }
  2088.  
  2089. UInt32 FRApp::GetClientPos(TEClient* pClient)
  2090. {
  2091.     if(pClient == m_apClients[0])
  2092.         return 0;
  2093.     else if(pClient == m_apClients[1])
  2094.         return 1;
  2095.     else if(pClient == m_apClients[2])
  2096.         return 2;
  2097.  
  2098.     return 0;
  2099. }
  2100.  
  2101. void FRApp::StartNetworkRace(void)
  2102. {
  2103.     FRCountdown Msg;
  2104.  
  2105.     Msg.ulMsgType = FRCOUNTDOWN;
  2106.     Msg.ucState = 1;
  2107.  
  2108.     memset(m_apCars, 0, sizeof(FRCar*) * 4);
  2109.  
  2110.     m_pCar = m_apCars[0] = GetCar(m_CurrCar, m_aStartPositions[3], m_aStartRotations[3]);
  2111.     m_pCar->m_DriverName = m_PlayerName;
  2112.     m_pCar->m_Type = LOCAL;
  2113.     m_pEngine->AddObjectToWorld(m_pCar);
  2114.  
  2115.     m_aulPosition[0] = 0;
  2116.     m_aulPosition[1] = 1;
  2117.     m_aulPosition[2] = 2;
  2118.     m_aulPosition[3] = 3;
  2119.  
  2120.     m_GameState = SERVERRACE;
  2121.     m_pEngine->ShowCursor(false);
  2122.     m_bShowAbortMenu = false;
  2123.  
  2124.     for(UInt32 ulCount = 0; ulCount < m_ulNumClients; ulCount++)
  2125.     {
  2126.         m_apCars[1+ulCount] = GetCar(m_aClientCars[ulCount], m_aStartPositions[2-ulCount], m_aStartRotations[2-ulCount]);
  2127.         m_apCars[1+ulCount]->m_Type = NETWORK;
  2128.         m_apCars[1+ulCount]->m_DriverName = m_apClients[ulCount]->acName;
  2129.         m_pEngine->AddObjectToWorld(m_apCars[1+ulCount]);
  2130.     }
  2131.  
  2132.     TETextureManager::GetTextureManager()->ReleaseUnusedTextures();
  2133.     TEModelManager::GetModelManager()->FreeUnusedModels();
  2134.     TESoundManager::GetSoundManager()->FreeUnusedSounds();
  2135.  
  2136.     m_pNetworkManager->SendDataToAllClients(&Msg, sizeof(Msg));
  2137.  
  2138.     m_ulCountdown = m_pTimer->GetTime();
  2139. }
  2140.  
  2141. FRCar* FRApp::GetCar(FRCarName &rCar, TEVector &rCenter, Float fInitYRot)
  2142. {
  2143.     FRCar* pCar;
  2144.  
  2145.     switch(rCar){
  2146.     case PICKUP:
  2147.         pCar = new FRPickup(rCenter, fInitYRot);
  2148.         break;
  2149.     case MONSTERHUMMER:
  2150.         pCar = new FRMonsterHummer(rCenter, fInitYRot);
  2151.         break;
  2152.     case HUMMER:
  2153.         pCar = new FRHummer(rCenter, fInitYRot);
  2154.         break;
  2155.     case GOLF:
  2156.         pCar = new FRGolf(rCenter, fInitYRot);
  2157.         break;
  2158.     case FUNERALCAR:
  2159.         pCar = new FRFuneralCar(rCenter, fInitYRot);
  2160.         break;
  2161.     case DODGE:
  2162.         pCar = new FRDodge(rCenter, fInitYRot);
  2163.         break;
  2164.     case COP:
  2165.         pCar = new FRCop(rCenter, fInitYRot);
  2166.         break;
  2167.     case AMBULANCE:
  2168.         pCar = new FRAmbulance(rCenter, fInitYRot);
  2169.         break;
  2170.     default:
  2171.     case ACLASS:
  2172.         pCar = new FRAClass(rCenter, fInitYRot);
  2173.         break;
  2174.     };
  2175.  
  2176.     return pCar;
  2177. }